<!DOCTYPE html>
<html lang="en-US">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <title>C++面向对象高级编程（上） | whoway</title>
    <meta name="description" content="Personal Blog Website">
    <link rel="icon" href="/images/photo.jpg">
  <link rel="manifest" href="/images/photo.jpg">
  <link rel="apple-touch-icon" href="/images/photo.jpg">
  <meta http-quiv="pragma" cotent="no-cache">
  <meta http-quiv="pragma" cotent="no-cache,must-revalidate">
  <meta http-quiv="expires" cotent="0">
    
    <link rel="preload" href="/assets/css/0.styles.0dbae9ec.css" as="style"><link rel="preload" href="/assets/js/app.c70e21ad.js" as="script"><link rel="preload" href="/assets/js/28.9523cb32.js" as="script"><link rel="prefetch" href="/assets/js/10.15222a53.js"><link rel="prefetch" href="/assets/js/100.7e0e5a86.js"><link rel="prefetch" href="/assets/js/101.efd59f25.js"><link rel="prefetch" href="/assets/js/102.dfbdc06c.js"><link rel="prefetch" href="/assets/js/103.d3ab2109.js"><link rel="prefetch" href="/assets/js/104.117957ef.js"><link rel="prefetch" href="/assets/js/105.046e8ff3.js"><link rel="prefetch" href="/assets/js/106.aebdc17d.js"><link rel="prefetch" href="/assets/js/107.248733c2.js"><link rel="prefetch" href="/assets/js/108.a2fecadc.js"><link rel="prefetch" href="/assets/js/109.35196857.js"><link rel="prefetch" href="/assets/js/11.770642f2.js"><link rel="prefetch" href="/assets/js/110.cf3d973c.js"><link rel="prefetch" href="/assets/js/111.f985889a.js"><link rel="prefetch" href="/assets/js/112.ad614f41.js"><link rel="prefetch" href="/assets/js/113.f666653c.js"><link rel="prefetch" href="/assets/js/114.c6c3f384.js"><link rel="prefetch" href="/assets/js/115.e51d3c2f.js"><link rel="prefetch" href="/assets/js/116.4f4b39f5.js"><link rel="prefetch" href="/assets/js/117.99352e11.js"><link rel="prefetch" href="/assets/js/118.c6ae6572.js"><link rel="prefetch" href="/assets/js/119.4ccbe778.js"><link rel="prefetch" href="/assets/js/12.042a92ff.js"><link rel="prefetch" href="/assets/js/120.edda1c4f.js"><link rel="prefetch" href="/assets/js/121.30a638ed.js"><link rel="prefetch" href="/assets/js/122.6efcefb1.js"><link rel="prefetch" href="/assets/js/123.91e6665b.js"><link rel="prefetch" href="/assets/js/124.f27e3d7e.js"><link rel="prefetch" href="/assets/js/125.c75712d5.js"><link rel="prefetch" href="/assets/js/126.ed756cce.js"><link rel="prefetch" href="/assets/js/127.2f06c74c.js"><link rel="prefetch" href="/assets/js/128.d5f6f30e.js"><link rel="prefetch" href="/assets/js/129.508b7eed.js"><link rel="prefetch" href="/assets/js/13.b5280c37.js"><link rel="prefetch" href="/assets/js/130.dc05f9aa.js"><link rel="prefetch" href="/assets/js/131.e0ba69b1.js"><link rel="prefetch" href="/assets/js/132.d79bcaa4.js"><link rel="prefetch" href="/assets/js/133.34acc01a.js"><link rel="prefetch" href="/assets/js/134.dabf64d5.js"><link rel="prefetch" href="/assets/js/135.ad90c915.js"><link rel="prefetch" href="/assets/js/136.dbb0074f.js"><link rel="prefetch" href="/assets/js/137.284ad365.js"><link rel="prefetch" href="/assets/js/138.a4b6856f.js"><link rel="prefetch" href="/assets/js/139.c9c1e20f.js"><link rel="prefetch" href="/assets/js/14.df02ba38.js"><link rel="prefetch" href="/assets/js/140.8b0a9269.js"><link rel="prefetch" href="/assets/js/141.9c7759c5.js"><link rel="prefetch" href="/assets/js/142.a4201a82.js"><link rel="prefetch" href="/assets/js/143.d7da6e8c.js"><link rel="prefetch" href="/assets/js/144.5e48e65d.js"><link rel="prefetch" href="/assets/js/145.a0e2633c.js"><link rel="prefetch" href="/assets/js/146.3c775f9b.js"><link rel="prefetch" href="/assets/js/147.22add89a.js"><link rel="prefetch" href="/assets/js/148.cfde1009.js"><link rel="prefetch" href="/assets/js/149.ffc835b5.js"><link rel="prefetch" href="/assets/js/15.fbdfc4ee.js"><link rel="prefetch" href="/assets/js/150.406c4b20.js"><link rel="prefetch" href="/assets/js/151.b2040eea.js"><link rel="prefetch" href="/assets/js/152.7bc65661.js"><link rel="prefetch" href="/assets/js/153.1d7c65e3.js"><link rel="prefetch" href="/assets/js/154.1309de49.js"><link rel="prefetch" href="/assets/js/155.81d3ee1f.js"><link rel="prefetch" href="/assets/js/156.154a4ef2.js"><link rel="prefetch" href="/assets/js/16.e5eb6147.js"><link rel="prefetch" href="/assets/js/17.57853c4a.js"><link rel="prefetch" href="/assets/js/18.cb9d7518.js"><link rel="prefetch" href="/assets/js/19.f354dc47.js"><link rel="prefetch" href="/assets/js/2.570d8a23.js"><link rel="prefetch" href="/assets/js/20.b5af7fad.js"><link rel="prefetch" href="/assets/js/21.0b1928fe.js"><link rel="prefetch" href="/assets/js/22.f78666de.js"><link rel="prefetch" href="/assets/js/23.29c3f366.js"><link rel="prefetch" href="/assets/js/24.6f596516.js"><link rel="prefetch" href="/assets/js/25.14067b60.js"><link rel="prefetch" href="/assets/js/26.74ba4989.js"><link rel="prefetch" href="/assets/js/27.13d60edd.js"><link rel="prefetch" href="/assets/js/29.8ec842e9.js"><link rel="prefetch" href="/assets/js/3.3fb3d2e0.js"><link rel="prefetch" href="/assets/js/30.805597a8.js"><link rel="prefetch" href="/assets/js/31.831b195d.js"><link rel="prefetch" href="/assets/js/32.063c672d.js"><link rel="prefetch" href="/assets/js/33.6d93fac3.js"><link rel="prefetch" href="/assets/js/34.56e8263c.js"><link rel="prefetch" href="/assets/js/35.dbe688bb.js"><link rel="prefetch" href="/assets/js/36.dc5af2c1.js"><link rel="prefetch" href="/assets/js/37.0a7494f6.js"><link rel="prefetch" href="/assets/js/38.fe4fc171.js"><link rel="prefetch" href="/assets/js/39.f5ed5e92.js"><link rel="prefetch" href="/assets/js/4.2c405ec8.js"><link rel="prefetch" href="/assets/js/40.fe7e2714.js"><link rel="prefetch" href="/assets/js/41.30b0811d.js"><link rel="prefetch" href="/assets/js/42.76f52d62.js"><link rel="prefetch" href="/assets/js/43.e7bb0817.js"><link rel="prefetch" href="/assets/js/44.ead0e883.js"><link rel="prefetch" href="/assets/js/45.235df046.js"><link rel="prefetch" href="/assets/js/46.5f09e829.js"><link rel="prefetch" href="/assets/js/47.67116354.js"><link rel="prefetch" href="/assets/js/48.31f34543.js"><link rel="prefetch" href="/assets/js/49.10b5ebba.js"><link rel="prefetch" href="/assets/js/5.6f47322c.js"><link rel="prefetch" href="/assets/js/50.c0f0b7f1.js"><link rel="prefetch" href="/assets/js/51.5143f3bf.js"><link rel="prefetch" href="/assets/js/52.eeddfd48.js"><link rel="prefetch" href="/assets/js/53.eb790db5.js"><link rel="prefetch" href="/assets/js/54.8fe5421c.js"><link rel="prefetch" href="/assets/js/55.d8f9004b.js"><link rel="prefetch" href="/assets/js/56.62ac9b92.js"><link rel="prefetch" href="/assets/js/57.a9caec0d.js"><link rel="prefetch" href="/assets/js/58.f93fc522.js"><link rel="prefetch" href="/assets/js/59.a81a03aa.js"><link rel="prefetch" href="/assets/js/6.8c2ea393.js"><link rel="prefetch" href="/assets/js/60.ab782775.js"><link rel="prefetch" href="/assets/js/61.6dd12daf.js"><link rel="prefetch" href="/assets/js/62.76f4b01f.js"><link rel="prefetch" href="/assets/js/63.6f8a4742.js"><link rel="prefetch" href="/assets/js/64.6f8bb1fa.js"><link rel="prefetch" href="/assets/js/65.4120a44b.js"><link rel="prefetch" href="/assets/js/66.360c2d2b.js"><link rel="prefetch" href="/assets/js/67.26f84d32.js"><link rel="prefetch" href="/assets/js/68.68f45e5e.js"><link rel="prefetch" href="/assets/js/69.e311eb56.js"><link rel="prefetch" href="/assets/js/7.6762b2d7.js"><link rel="prefetch" href="/assets/js/70.cea82674.js"><link rel="prefetch" href="/assets/js/71.783ddcf7.js"><link rel="prefetch" href="/assets/js/72.e5467385.js"><link rel="prefetch" href="/assets/js/73.b8fb681b.js"><link rel="prefetch" href="/assets/js/74.1bae37db.js"><link rel="prefetch" href="/assets/js/75.024387e5.js"><link rel="prefetch" href="/assets/js/76.a8e53010.js"><link rel="prefetch" href="/assets/js/77.8c55500a.js"><link rel="prefetch" href="/assets/js/78.7ce90bf5.js"><link rel="prefetch" href="/assets/js/79.ef71713f.js"><link rel="prefetch" href="/assets/js/8.788a6364.js"><link rel="prefetch" href="/assets/js/80.acad589d.js"><link rel="prefetch" href="/assets/js/81.02670d10.js"><link rel="prefetch" href="/assets/js/82.53b7b1ac.js"><link rel="prefetch" href="/assets/js/83.99eb8581.js"><link rel="prefetch" href="/assets/js/84.d1535ce3.js"><link rel="prefetch" href="/assets/js/85.fe2b7de9.js"><link rel="prefetch" href="/assets/js/86.41850272.js"><link rel="prefetch" href="/assets/js/87.1cdc6df9.js"><link rel="prefetch" href="/assets/js/88.01bf3461.js"><link rel="prefetch" href="/assets/js/89.17c69819.js"><link rel="prefetch" href="/assets/js/9.3813842d.js"><link rel="prefetch" href="/assets/js/90.f6ae7e35.js"><link rel="prefetch" href="/assets/js/91.507bc284.js"><link rel="prefetch" href="/assets/js/92.90551782.js"><link rel="prefetch" href="/assets/js/93.dc442d78.js"><link rel="prefetch" href="/assets/js/94.315f4e94.js"><link rel="prefetch" href="/assets/js/95.ccd6c6bf.js"><link rel="prefetch" href="/assets/js/96.0c6d89d0.js"><link rel="prefetch" href="/assets/js/97.1a9f10a9.js"><link rel="prefetch" href="/assets/js/98.43be3caa.js"><link rel="prefetch" href="/assets/js/99.54c8207b.js">
    <link rel="stylesheet" href="/assets/css/0.styles.0dbae9ec.css">
  </head>
  <body>
    <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/" class="home-link router-link-active"><!----> <span class="site-name">whoway</span></a> <div class="links" style="max-width:nullpx;"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><div class="dropdown-wrapper"><a class="dropdown-title"><span class="title">🎓Coding</span> <span class="arrow right"></span></a> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/00.Coding/TheBeautyOfProgramming/" class="nav-link">🔖编程之美题解</a></li><li class="dropdown-item"><!----> <a href="/00.Coding/CodeWarehouse/" class="nav-link">🔖代码意识流</a></li></ul></div></div><div class="nav-item"><div class="dropdown-wrapper"><a class="dropdown-title"><span class="title">🚀语言</span> <span class="arrow right"></span></a> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/01.Language/Overview/" class="nav-link">🔖概述</a></li><li class="dropdown-item"><!----> <a href="/01.Language/C/" class="nav-link">⭐️C</a></li><li class="dropdown-item"><!----> <a href="/01.Language/Cpp/" class="nav-link router-link-active">🚀C++</a></li><li class="dropdown-item"><!----> <a href="/01.Language/Java/" class="nav-link">☕️Java</a></li><li class="dropdown-item"><!----> <a href="/01.Language/Python/" class="nav-link">🧩Python3</a></li></ul></div></div><div class="nav-item"><a href="/02.Hardware/" class="nav-link">✔️硬件基础</a></div><div class="nav-item"><div class="dropdown-wrapper"><a class="dropdown-title"><span class="title">⭐️软件基础</span> <span class="arrow right"></span></a> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/03.Software/01.DataStructureAndAlgorithm/" class="nav-link">🐾数据结构和算法</a></li><li class="dropdown-item"><!----> <a href="/03.Software/02.OS/" class="nav-link">💻操作系统</a></li><li class="dropdown-item"><!----> <a href="/03.Software/03.Net/" class="nav-link">☁️计算机网络</a></li><li class="dropdown-item"><!----> <a href="/03.Software/04.SE/" class="nav-link">✅软件工程</a></li></ul></div></div><div class="nav-item"><a href="/04.Database/" class="nav-link">🎨数据库</a></div><div class="nav-item"><a href="/05.Engineer/" class="nav-link">🔖学术/工程</a></div><div class="nav-item"><div class="dropdown-wrapper"><a class="dropdown-title"><span class="title">⚙️工具</span> <span class="arrow right"></span></a> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/06.Tools/01.employment/" class="nav-link">🔖求职</a></li><li class="dropdown-item"><!----> <a href="/06.Tools/02.efficiency/" class="nav-link">🚀效能</a></li><li class="dropdown-item"><!----> <a href="/06.Tools/03.windows/" class="nav-link">⚙️Windows</a></li><li class="dropdown-item"><!----> <a href="/06.Tools/04.design/" class="nav-link">🧩设计</a></li><li class="dropdown-item"><!----> <a href="/06.Tools/05.linux/" class="nav-link">🐉Linux</a></li></ul></div></div><div class="nav-item"><a href="https://github.com/whoway" target="_blank" rel="noopener noreferrer" class="nav-link external">
  GitHub
  <svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></div> <!----></nav></div></header> <div class="sidebar-mask"></div> <div class="sidebar"><nav class="nav-links"><div class="nav-item"><div class="dropdown-wrapper"><a class="dropdown-title"><span class="title">🎓Coding</span> <span class="arrow right"></span></a> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/00.Coding/TheBeautyOfProgramming/" class="nav-link">🔖编程之美题解</a></li><li class="dropdown-item"><!----> <a href="/00.Coding/CodeWarehouse/" class="nav-link">🔖代码意识流</a></li></ul></div></div><div class="nav-item"><div class="dropdown-wrapper"><a class="dropdown-title"><span class="title">🚀语言</span> <span class="arrow right"></span></a> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/01.Language/Overview/" class="nav-link">🔖概述</a></li><li class="dropdown-item"><!----> <a href="/01.Language/C/" class="nav-link">⭐️C</a></li><li class="dropdown-item"><!----> <a href="/01.Language/Cpp/" class="nav-link router-link-active">🚀C++</a></li><li class="dropdown-item"><!----> <a href="/01.Language/Java/" class="nav-link">☕️Java</a></li><li class="dropdown-item"><!----> <a href="/01.Language/Python/" class="nav-link">🧩Python3</a></li></ul></div></div><div class="nav-item"><a href="/02.Hardware/" class="nav-link">✔️硬件基础</a></div><div class="nav-item"><div class="dropdown-wrapper"><a class="dropdown-title"><span class="title">⭐️软件基础</span> <span class="arrow right"></span></a> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/03.Software/01.DataStructureAndAlgorithm/" class="nav-link">🐾数据结构和算法</a></li><li class="dropdown-item"><!----> <a href="/03.Software/02.OS/" class="nav-link">💻操作系统</a></li><li class="dropdown-item"><!----> <a href="/03.Software/03.Net/" class="nav-link">☁️计算机网络</a></li><li class="dropdown-item"><!----> <a href="/03.Software/04.SE/" class="nav-link">✅软件工程</a></li></ul></div></div><div class="nav-item"><a href="/04.Database/" class="nav-link">🎨数据库</a></div><div class="nav-item"><a href="/05.Engineer/" class="nav-link">🔖学术/工程</a></div><div class="nav-item"><div class="dropdown-wrapper"><a class="dropdown-title"><span class="title">⚙️工具</span> <span class="arrow right"></span></a> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/06.Tools/01.employment/" class="nav-link">🔖求职</a></li><li class="dropdown-item"><!----> <a href="/06.Tools/02.efficiency/" class="nav-link">🚀效能</a></li><li class="dropdown-item"><!----> <a href="/06.Tools/03.windows/" class="nav-link">⚙️Windows</a></li><li class="dropdown-item"><!----> <a href="/06.Tools/04.design/" class="nav-link">🧩设计</a></li><li class="dropdown-item"><!----> <a href="/06.Tools/05.linux/" class="nav-link">🐉Linux</a></li></ul></div></div><div class="nav-item"><a href="https://github.com/whoway" target="_blank" rel="noopener noreferrer" class="nav-link external">
  GitHub
  <svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></div> <!----></nav>  <ul class="sidebar-links"><li><div class="sidebar-group first"><p class="sidebar-heading open"><span>C++面向对象高级编程（上）</span> <!----></p> <ul class="sidebar-group-items"><li><a href="/01.Language/Cpp/PPT01.C%2B%2B%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1%E9%AB%98%E7%BA%A7%E7%BC%96%E7%A8%8B%E4%B8%8A.html#📑目录" class="sidebar-link">📑目录</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/01.Language/Cpp/PPT01.C%2B%2B%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1%E9%AB%98%E7%BA%A7%E7%BC%96%E7%A8%8B%E4%B8%8A.html#⭐️中英对照" class="sidebar-link">⭐️中英对照</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/01.Language/Cpp/PPT01.C%2B%2B%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1%E9%AB%98%E7%BA%A7%E7%BC%96%E7%A8%8B%E4%B8%8A.html#_01-c-编程简介" class="sidebar-link">01.C++编程简介</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/01.Language/Cpp/PPT01.C%2B%2B%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1%E9%AB%98%E7%BA%A7%E7%BC%96%E7%A8%8B%E4%B8%8A.html#_1-1-应该具备的基础" class="sidebar-link">1.1.应该具备的基础</a></li><li class="sidebar-sub-header"><a href="/01.Language/Cpp/PPT01.C%2B%2B%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1%E9%AB%98%E7%BA%A7%E7%BC%96%E7%A8%8B%E4%B8%8A.html#_1-2-我们的目标✅" class="sidebar-link">1.2.我们的目标✅</a></li><li class="sidebar-sub-header"><a href="/01.Language/Cpp/PPT01.C%2B%2B%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1%E9%AB%98%E7%BA%A7%E7%BC%96%E7%A8%8B%E4%B8%8A.html#_1-3-c-演化" class="sidebar-link">1.3.C++演化</a></li><li class="sidebar-sub-header"><a href="/01.Language/Cpp/PPT01.C%2B%2B%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1%E9%AB%98%E7%BA%A7%E7%BC%96%E7%A8%8B%E4%B8%8A.html#_1-4-学习c-是学什么？『2部分』" class="sidebar-link">1.4.学习C++是学什么？『2部分』</a></li><li class="sidebar-sub-header"><a href="/01.Language/Cpp/PPT01.C%2B%2B%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1%E9%AB%98%E7%BA%A7%E7%BC%96%E7%A8%8B%E4%B8%8A.html#_1-5-书籍推荐" class="sidebar-link">1.5.书籍推荐</a></li></ul></li><li><a href="/01.Language/Cpp/PPT01.C%2B%2B%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1%E9%AB%98%E7%BA%A7%E7%BC%96%E7%A8%8B%E4%B8%8A.html#✅语言部分" class="sidebar-link">✅语言部分</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/01.Language/Cpp/PPT01.C%2B%2B%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1%E9%AB%98%E7%BA%A7%E7%BC%96%E7%A8%8B%E4%B8%8A.html#_02-头文件与类的声明" class="sidebar-link">02.头文件与类的声明</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/01.Language/Cpp/PPT01.C%2B%2B%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1%E9%AB%98%E7%BA%A7%E7%BC%96%E7%A8%8B%E4%B8%8A.html#_2-1-obp和oop模式的对比⭐️" class="sidebar-link">2.1.OBP和OOP模式的对比⭐️</a></li><li class="sidebar-sub-header"><a href="/01.Language/Cpp/PPT01.C%2B%2B%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1%E9%AB%98%E7%BA%A7%E7%BC%96%E7%A8%8B%E4%B8%8A.html#_2-2-代码格式⭐️" class="sidebar-link">2.2.代码格式⭐️</a></li><li class="sidebar-sub-header"><a href="/01.Language/Cpp/PPT01.C%2B%2B%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1%E9%AB%98%E7%BA%A7%E7%BC%96%E7%A8%8B%E4%B8%8A.html#_2-3-编程习惯-防卫式声明⭐️" class="sidebar-link">2.3.编程习惯-防卫式声明⭐️</a></li><li class="sidebar-sub-header"><a href="/01.Language/Cpp/PPT01.C%2B%2B%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1%E9%AB%98%E7%BA%A7%E7%BC%96%E7%A8%8B%E4%B8%8A.html#_2-4-header（头文件）的布局⭐️" class="sidebar-link">2.4.Header（头文件）的布局⭐️</a></li></ul></li><li><a href="/01.Language/Cpp/PPT01.C%2B%2B%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1%E9%AB%98%E7%BA%A7%E7%BC%96%E7%A8%8B%E4%B8%8A.html#_03-构造函数-ctor" class="sidebar-link">03.构造函数(ctor)</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/01.Language/Cpp/PPT01.C%2B%2B%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1%E9%AB%98%E7%BA%A7%E7%BC%96%E7%A8%8B%E4%B8%8A.html#_3-1-inline-内联-函数⭐️" class="sidebar-link">3.1.inline(内联)函数⭐️</a></li><li class="sidebar-sub-header"><a href="/01.Language/Cpp/PPT01.C%2B%2B%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1%E9%AB%98%E7%BA%A7%E7%BC%96%E7%A8%8B%E4%B8%8A.html#_3-2-访问级别-access-level-⭐️" class="sidebar-link">3.2.访问级别(access level)⭐️</a></li><li class="sidebar-sub-header"><a href="/01.Language/Cpp/PPT01.C%2B%2B%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1%E9%AB%98%E7%BA%A7%E7%BC%96%E7%A8%8B%E4%B8%8A.html#_3-3-class-『without』-pointers-members的特点⭐️" class="sidebar-link">3.3.class 『without』 pointers members的特点⭐️</a></li><li class="sidebar-sub-header"><a href="/01.Language/Cpp/PPT01.C%2B%2B%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1%E9%AB%98%E7%BA%A7%E7%BC%96%E7%A8%8B%E4%B8%8A.html#_3-4-函数重载常常发生在" class="sidebar-link">3.4.函数重载常常发生在</a></li></ul></li><li><a href="/01.Language/Cpp/PPT01.C%2B%2B%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1%E9%AB%98%E7%BA%A7%E7%BC%96%E7%A8%8B%E4%B8%8A.html#_04-参数传递与返回值" class="sidebar-link">04.参数传递与返回值</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/01.Language/Cpp/PPT01.C%2B%2B%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1%E9%AB%98%E7%BA%A7%E7%BC%96%E7%A8%8B%E4%B8%8A.html#_4-1-构造函数如果是private？⭐️" class="sidebar-link">4.1.构造函数如果是private？⭐️</a></li><li class="sidebar-sub-header"><a href="/01.Language/Cpp/PPT01.C%2B%2B%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1%E9%AB%98%E7%BA%A7%E7%BC%96%E7%A8%8B%E4%B8%8A.html#奇怪的问题：static莫不是为了单例模式而生的？" class="sidebar-link">奇怪的问题：static莫不是为了单例模式而生的？</a></li><li class="sidebar-sub-header"><a href="/01.Language/Cpp/PPT01.C%2B%2B%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1%E9%AB%98%E7%BA%A7%E7%BC%96%E7%A8%8B%E4%B8%8A.html#_4-2-const成员函数？-奇怪的语法" class="sidebar-link">4.2.const成员函数？-奇怪的语法</a></li><li class="sidebar-sub-header"><a href="/01.Language/Cpp/PPT01.C%2B%2B%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1%E9%AB%98%E7%BA%A7%E7%BC%96%E7%A8%8B%E4%B8%8A.html#_4-3-『友元』" class="sidebar-link">4.3.『友元』</a></li><li class="sidebar-sub-header"><a href="/01.Language/Cpp/PPT01.C%2B%2B%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1%E9%AB%98%E7%BA%A7%E7%BC%96%E7%A8%8B%E4%B8%8A.html#⭐️相同class的各个objects互为friends（友元）「记忆」" class="sidebar-link">⭐️相同class的各个objects互为friends（友元）「记忆」</a></li><li class="sidebar-sub-header"><a href="/01.Language/Cpp/PPT01.C%2B%2B%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1%E9%AB%98%E7%BA%A7%E7%BC%96%E7%A8%8B%E4%B8%8A.html#『习惯』" class="sidebar-link">『习惯』</a></li></ul></li><li><a href="/01.Language/Cpp/PPT01.C%2B%2B%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1%E9%AB%98%E7%BA%A7%E7%BC%96%E7%A8%8B%E4%B8%8A.html#_05-操作符重载与『临时对象』" class="sidebar-link">05.操作符重载与『临时对象』</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/01.Language/Cpp/PPT01.C%2B%2B%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1%E9%AB%98%E7%BA%A7%E7%BC%96%E7%A8%8B%E4%B8%8A.html#_5-1-『临时对象』重要" class="sidebar-link">5.1.『临时对象』重要</a></li><li class="sidebar-sub-header"><a href="/01.Language/Cpp/PPT01.C%2B%2B%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1%E9%AB%98%E7%BA%A7%E7%BC%96%E7%A8%8B%E4%B8%8A.html#『临时对象特殊语法』" class="sidebar-link">『临时对象特殊语法』</a></li><li class="sidebar-sub-header"><a href="/01.Language/Cpp/PPT01.C%2B%2B%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1%E9%AB%98%E7%BA%A7%E7%BC%96%E7%A8%8B%E4%B8%8A.html#『重载-操作符的特殊』『易错』" class="sidebar-link">『重载&lt;&lt;操作符的特殊』『易错』</a></li></ul></li><li><a href="/01.Language/Cpp/PPT01.C%2B%2B%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1%E9%AB%98%E7%BA%A7%E7%BC%96%E7%A8%8B%E4%B8%8A.html#_06-复习complex类的实现过程" class="sidebar-link">06.复习Complex类的实现过程</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/01.Language/Cpp/PPT01.C%2B%2B%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1%E9%AB%98%E7%BA%A7%E7%BC%96%E7%A8%8B%E4%B8%8A.html#『class之不带指针部分讲完』" class="sidebar-link">『class之不带指针部分讲完』</a></li></ul></li><li><a href="/01.Language/Cpp/PPT01.C%2B%2B%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1%E9%AB%98%E7%BA%A7%E7%BC%96%E7%A8%8B%E4%B8%8A.html#_07-big-three⭐️『class-with-pointer-members开始』" class="sidebar-link">07.Big Three⭐️『class with pointer members开始』</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/01.Language/Cpp/PPT01.C%2B%2B%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1%E9%AB%98%E7%BA%A7%E7%BC%96%E7%A8%8B%E4%B8%8A.html#_7-1-记忆3大函数：拷贝构造函数，拷贝赋值函数，析构函数" class="sidebar-link">7.1.记忆3大函数：拷贝构造函数，拷贝赋值函数，析构函数</a></li><li class="sidebar-sub-header"><a href="/01.Language/Cpp/PPT01.C%2B%2B%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1%E9%AB%98%E7%BA%A7%E7%BC%96%E7%A8%8B%E4%B8%8A.html#_7-2-拷贝构造" class="sidebar-link">7.2.拷贝构造</a></li><li class="sidebar-sub-header"><a href="/01.Language/Cpp/PPT01.C%2B%2B%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1%E9%AB%98%E7%BA%A7%E7%BC%96%E7%A8%8B%E4%B8%8A.html#_7-3-拷贝赋值函数『注意概念，非常容易错！』" class="sidebar-link">7.3.拷贝赋值函数『注意概念，非常容易错！』</a></li><li class="sidebar-sub-header"><a href="/01.Language/Cpp/PPT01.C%2B%2B%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1%E9%AB%98%E7%BA%A7%E7%BC%96%E7%A8%8B%E4%B8%8A.html#_7-4-大师风范-检测是否：『坑点』自我赋值-self-assignment-⭐️⭐️" class="sidebar-link">7.4.大师风范-检测是否：『坑点』自我赋值(self assignment)⭐️⭐️</a></li></ul></li><li><a href="/01.Language/Cpp/PPT01.C%2B%2B%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1%E9%AB%98%E7%BA%A7%E7%BC%96%E7%A8%8B%E4%B8%8A.html#_08-堆，栈与内存管理" class="sidebar-link">08.堆，栈与内存管理</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/01.Language/Cpp/PPT01.C%2B%2B%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1%E9%AB%98%E7%BA%A7%E7%BC%96%E7%A8%8B%E4%B8%8A.html#_8-1-stack-objects的生命期" class="sidebar-link">8.1.stack objects的生命期</a></li><li class="sidebar-sub-header"><a href="/01.Language/Cpp/PPT01.C%2B%2B%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1%E9%AB%98%E7%BA%A7%E7%BC%96%E7%A8%8B%E4%B8%8A.html#_8-2-static-local-objects的生命期" class="sidebar-link">8.2.static local objects的生命期</a></li><li class="sidebar-sub-header"><a href="/01.Language/Cpp/PPT01.C%2B%2B%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1%E9%AB%98%E7%BA%A7%E7%BC%96%E7%A8%8B%E4%B8%8A.html#_8-3-global-objects的生命期" class="sidebar-link">8.3.global objects的生命期</a></li><li class="sidebar-sub-header"><a href="/01.Language/Cpp/PPT01.C%2B%2B%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1%E9%AB%98%E7%BA%A7%E7%BC%96%E7%A8%8B%E4%B8%8A.html#_8-4-heap-objects的生命期" class="sidebar-link">8.4.heap objects的生命期</a></li><li class="sidebar-sub-header"><a href="/01.Language/Cpp/PPT01.C%2B%2B%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1%E9%AB%98%E7%BA%A7%E7%BC%96%E7%A8%8B%E4%B8%8A.html#_16的倍数的使用" class="sidebar-link">16的倍数的使用</a></li><li class="sidebar-sub-header"><a href="/01.Language/Cpp/PPT01.C%2B%2B%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1%E9%AB%98%E7%BA%A7%E7%BC%96%E7%A8%8B%E4%B8%8A.html#『核心』delete的析构次数-free大小" class="sidebar-link">『核心』delete的析构次数+free大小</a></li></ul></li><li><a href="/01.Language/Cpp/PPT01.C%2B%2B%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1%E9%AB%98%E7%BA%A7%E7%BC%96%E7%A8%8B%E4%B8%8A.html#⏳09-复习string类的实现过程『ing" class="sidebar-link">⏳09.复习String类的实现过程『ing</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/01.Language/Cpp/PPT01.C%2B%2B%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1%E9%AB%98%E7%BA%A7%E7%BC%96%E7%A8%8B%E4%B8%8A.html#_10-扩展补充：类模板，函数模板，及其他" class="sidebar-link">10.扩展补充：类模板，函数模板，及其他</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/01.Language/Cpp/PPT01.C%2B%2B%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1%E9%AB%98%E7%BA%A7%E7%BC%96%E7%A8%8B%E4%B8%8A.html#_10-1-进一步扩展static细节』⭐️" class="sidebar-link">10.1.进一步扩展static细节』⭐️</a></li><li class="sidebar-sub-header"><a href="/01.Language/Cpp/PPT01.C%2B%2B%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1%E9%AB%98%E7%BA%A7%E7%BC%96%E7%A8%8B%E4%B8%8A.html#_10-2-进一步补充ctors放在private里面-单例模式" class="sidebar-link">10.2.进一步补充ctors放在private里面+单例模式</a></li><li class="sidebar-sub-header"><a href="/01.Language/Cpp/PPT01.C%2B%2B%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1%E9%AB%98%E7%BA%A7%E7%BC%96%E7%A8%8B%E4%B8%8A.html#_10-3-进一步补充cout" class="sidebar-link">10.3.进一步补充cout</a></li><li class="sidebar-sub-header"><a href="/01.Language/Cpp/PPT01.C%2B%2B%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1%E9%AB%98%E7%BA%A7%E7%BC%96%E7%A8%8B%E4%B8%8A.html#_10-4-进一步补充class-template" class="sidebar-link">10.4.进一步补充class template</a></li><li class="sidebar-sub-header"><a href="/01.Language/Cpp/PPT01.C%2B%2B%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1%E9%AB%98%E7%BA%A7%E7%BC%96%E7%A8%8B%E4%B8%8A.html#_10-5-进一步补充function-template-argument-deduction（引数推导）⭐️" class="sidebar-link">10.5.进一步补充function template+argument deduction（引数推导）⭐️</a></li><li class="sidebar-sub-header"><a href="/01.Language/Cpp/PPT01.C%2B%2B%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1%E9%AB%98%E7%BA%A7%E7%BC%96%E7%A8%8B%E4%B8%8A.html#hacv疑问：类模板为什么不能自动推导数据类型？⭐️" class="sidebar-link">HACV疑问：类模板为什么不能自动推导数据类型？⭐️</a></li><li class="sidebar-sub-header"><a href="/01.Language/Cpp/PPT01.C%2B%2B%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1%E9%AB%98%E7%BA%A7%E7%BC%96%E7%A8%8B%E4%B8%8A.html#_10-6-进一步补充namespace" class="sidebar-link">10.6.进一步补充namespace</a></li></ul></li><li><a href="/01.Language/Cpp/PPT01.C%2B%2B%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1%E9%AB%98%E7%BA%A7%E7%BC%96%E7%A8%8B%E4%B8%8A.html#✅『类和类之间的关系开始』" class="sidebar-link">✅『类和类之间的关系开始』</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/01.Language/Cpp/PPT01.C%2B%2B%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1%E9%AB%98%E7%BA%A7%E7%BC%96%E7%A8%8B%E4%B8%8A.html#_11-组合-composition-与继承-inheritance" class="sidebar-link">11.组合(Composition)与继承(Inheritance)</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/01.Language/Cpp/PPT01.C%2B%2B%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1%E9%AB%98%E7%BA%A7%E7%BC%96%E7%A8%8B%E4%B8%8A.html#_11-1-composition（复合）" class="sidebar-link">11.1.Composition（复合）</a></li><li class="sidebar-sub-header"><a href="/01.Language/Cpp/PPT01.C%2B%2B%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1%E9%AB%98%E7%BA%A7%E7%BC%96%E7%A8%8B%E4%B8%8A.html#记忆『container和component』" class="sidebar-link">记忆『Container和Component』</a></li><li class="sidebar-sub-header"><a href="/01.Language/Cpp/PPT01.C%2B%2B%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1%E9%AB%98%E7%BA%A7%E7%BC%96%E7%A8%8B%E4%B8%8A.html#默认构造函数？？" class="sidebar-link">默认构造函数？？</a></li><li class="sidebar-sub-header"><a href="/01.Language/Cpp/PPT01.C%2B%2B%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1%E9%AB%98%E7%BA%A7%E7%BC%96%E7%A8%8B%E4%B8%8A.html#_11-2-delegation（委托）-编程手法pimpl⭐️" class="sidebar-link">11.2.Delegation（委托）+编程手法pImpl⭐️</a></li><li class="sidebar-sub-header"><a href="/01.Language/Cpp/PPT01.C%2B%2B%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1%E9%AB%98%E7%BA%A7%E7%BC%96%E7%A8%8B%E4%B8%8A.html#编译防火墙" class="sidebar-link">编译防火墙</a></li><li class="sidebar-sub-header"><a href="/01.Language/Cpp/PPT01.C%2B%2B%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1%E9%AB%98%E7%BA%A7%E7%BC%96%E7%A8%8B%E4%B8%8A.html#inheritance（继承）" class="sidebar-link">Inheritance（继承）</a></li><li class="sidebar-sub-header"><a href="/01.Language/Cpp/PPT01.C%2B%2B%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1%E9%AB%98%E7%BA%A7%E7%BC%96%E7%A8%8B%E4%B8%8A.html#继承到底怎么用？搭配虚函数" class="sidebar-link">继承到底怎么用？搭配虚函数</a></li></ul></li><li><a href="/01.Language/Cpp/PPT01.C%2B%2B%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1%E9%AB%98%E7%BA%A7%E7%BC%96%E7%A8%8B%E4%B8%8A.html#_12-虚函数与多态" class="sidebar-link">12.虚函数与多态</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/01.Language/Cpp/PPT01.C%2B%2B%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1%E9%AB%98%E7%BA%A7%E7%BC%96%E7%A8%8B%E4%B8%8A.html#_12-1-inheritance（继承）带有虚函数" class="sidebar-link">12.1.Inheritance（继承）带有虚函数</a></li><li class="sidebar-sub-header"><a href="/01.Language/Cpp/PPT01.C%2B%2B%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1%E9%AB%98%E7%BA%A7%E7%BC%96%E7%A8%8B%E4%B8%8A.html#_12-2-template-method（模板方法）" class="sidebar-link">12.2.Template Method（模板方法）</a></li><li class="sidebar-sub-header"><a href="/01.Language/Cpp/PPT01.C%2B%2B%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1%E9%AB%98%E7%BA%A7%E7%BC%96%E7%A8%8B%E4%B8%8A.html#_12-3-inheritance（继承）-composition（复合）关系下的构造和析构" class="sidebar-link">12.3.Inheritance（继承）+Composition（复合）关系下的构造和析构</a></li><li class="sidebar-sub-header"><a href="/01.Language/Cpp/PPT01.C%2B%2B%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1%E9%AB%98%E7%BA%A7%E7%BC%96%E7%A8%8B%E4%B8%8A.html#_12-4-inheritance（继承）-委托-delegation" class="sidebar-link">12.4.Inheritance（继承）+委托(Delegation)</a></li></ul></li><li><a href="/01.Language/Cpp/PPT01.C%2B%2B%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1%E9%AB%98%E7%BA%A7%E7%BC%96%E7%A8%8B%E4%B8%8A.html#_13-委托-delegation-相关设计" class="sidebar-link">13.委托(Delegation)相关设计</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/01.Language/Cpp/PPT01.C%2B%2B%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1%E9%AB%98%E7%BA%A7%E7%BC%96%E7%A8%8B%E4%B8%8A.html#_13-1-composite模式" class="sidebar-link">13.1.Composite模式</a></li><li class="sidebar-sub-header"><a href="/01.Language/Cpp/PPT01.C%2B%2B%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1%E9%AB%98%E7%BA%A7%E7%BC%96%E7%A8%8B%E4%B8%8A.html#_13-2-prototype（原型模式）" class="sidebar-link">13.2.Prototype（原型模式）</a></li><li class="sidebar-sub-header"><a href="/01.Language/Cpp/PPT01.C%2B%2B%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1%E9%AB%98%E7%BA%A7%E7%BC%96%E7%A8%8B%E4%B8%8A.html#static牛皮啊，hacv注" class="sidebar-link">static牛皮啊，HACV注</a></li></ul></li><li><a href="/01.Language/Cpp/PPT01.C%2B%2B%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1%E9%AB%98%E7%BA%A7%E7%BC%96%E7%A8%8B%E4%B8%8A.html#参考资料" class="sidebar-link">参考资料</a><ul class="sidebar-sub-headers"></ul></li></ul></div></li></ul> </div> <div class="page"> <div class="content"><h1 id="c-面向对象高级编程（上）"><a href="#c-面向对象高级编程（上）" class="header-anchor">#</a> C++面向对象高级编程（上）</h1> <ul><li>C++98</li> <li><strong>Object Based</strong>『基于对象的设计』</li> <li><strong>Object Oriented</strong> 『面向对象的设计』Object Oriented Progrmming, OOP</li></ul> <div class="language-txt line-numbers-mode"><pre class="language-text"><code>&lt;font style=&quot;background:yellow&quot;&gt;
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br></div></div><h2 id="📑目录"><a href="#📑目录" class="header-anchor">#</a> 📑目录</h2> <p>[TOC]</p> <div class="language-txt line-numbers-mode"><pre class="language-text"><code> 
05.操作符重载与『临时对象』
06.复习Complex类的实现过程『class中不带指针的设计』
07.3大函数：拷贝构造，拷贝复制，析构『Big Three』
08.堆，栈与内存管理
	- 区分：Stack对象和heap对象
09.复习String类的实现过程『class中带指针/引用的设计』
10.扩展补充：类模板，函数模板，及其他
11.组合与继承
12.虚函数与多态
13.委托相关设计
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br></div></div><h2 id="⭐️中英对照"><a href="#⭐️中英对照" class="header-anchor">#</a> ⭐️中英对照</h2> <blockquote><p>01.C++编程简介</p></blockquote> <ul><li>区分：</li> <li><ul><li><strong>Object Based</strong>『基于对象的设计』</li> <li><strong>Object Oriented</strong> 『面向对象的设计』</li></ul></li> <li>区分：
<ul><li>class without pointer members『class中不带指针/<strong>引用</strong>的设计』</li> <li>class with pointer members『注意，我们讨论的却是：class中带指针/<strong>引用</strong>的设计』</li></ul></li></ul> <blockquote><p>02.头文件与类的声明</p></blockquote> <ul><li><font style="background:yellow;">guard，v.防范，n.防护装置</font>，防御式声明</li> <li>（<font style="background:yellow;">class declarations，类-声明</font>）</li> <li>（<font style="background:yellow;">class definition，类-定义</font>）</li> <li>（<font style="background:yellow;">forward declarations，前置声明</font>）</li></ul> <blockquote><p>03.构造函数(ctor)</p></blockquote> <ul><li><p>constructor（ctor，构造函数）</p></li> <li><p><strong>『初始化列（initialization list）』</strong></p></li> <li><p><strong>assignments（赋值）</strong></p></li> <li><p><font style="background:yellow;">class with pointers members的<strong>必须</strong>有<code>copy ctor</code>和<code>copy op=</code></font></p></li> <li><p>Big Three『记忆』</p> <ul><li>copy ctor，拷贝构造函数
<ul><li>default copy ctor，默认的拷贝构造函数</li> <li>非默认的</li></ul></li> <li>copy assignment operator，拷贝赋值函数『copy op=』（注意：不要翻译成，拷贝复制函数。。。）
<ul><li>default copy op=</li> <li>非默认的</li></ul></li> <li>dtor，析构函数</li></ul></li> <li><p>重载<code>&lt;&lt;</code></p></li></ul> <h2 id="_01-c-编程简介"><a href="#_01-c-编程简介" class="header-anchor">#</a> 01.C++编程简介</h2> <ul><li>面向对象是1个<strong>观念</strong></li></ul> <h3 id="_1-1-应该具备的基础"><a href="#_1-1-应该具备的基础" class="header-anchor">#</a> 1.1.应该具备的基础</h3> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210710140800201.png" alt="image-20210710140800201"></p> <ul><li>作用域 (scope)	『比如说，<code>{}</code>里面的变数在里头的生命』</li></ul> <h3 id="_1-2-我们的目标✅"><a href="#_1-2-我们的目标✅" class="header-anchor">#</a> 1.2.我们的目标✅</h3> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210710140924654.png" alt="image-20210710140924654"></p> <p>培养正规的、大气的编程习惯『<strong>即使是小的程序，我们也希望，一出手就是有大家规范的正规的写法</strong>』</p> <p>要引导大家以良好的习惯来写C++的class 、因为C++代码中最重要的每一个单元都是1个class</p> <blockquote><p>class有2个很经典的分类：</p></blockquote> <h4 id="_1-2-1-『单个class设计』✅"><a href="#_1-2-1-『单个class设计』✅" class="header-anchor">#</a> 1.2.1.『<font style="background:yellow;">单个class设计</font>』✅</h4> <ul><li>又有一个名字：<strong>Object Based</strong> (基於對象)基于对象</li> <li>以良好的方式编写
<ul><li>C++ class『为什么写class呢？因为C++代码里面，每一个单元，最重要的一个单元就是一个class』</li> <li>class有下面2个很经典的分类：带不带pointer『这2种在设计上、思考上截然不同』</li></ul></li> <li>class without pointer members
<ul><li>Complex</li></ul></li> <li>class with pointer members
<ul><li>String</li></ul></li></ul> <h4 id="_1-2-2-『多个class』之间有某种关联的话✅"><a href="#_1-2-2-『多个class』之间有某种关联的话✅" class="header-anchor">#</a> 1.2.2.『<font style="background:yellow;">多个class</font>』之间有某种关联的话✅</h4> <ul><li>又叫：<strong>Object Oriented</strong> (面向對象）</li></ul> <div class="language-txt line-numbers-mode"><pre class="language-text"><code>//你将获得的代码
complex.h
complex-test.cpp

string.h
string-test.cpp
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br></div></div><h3 id="_1-3-c-演化"><a href="#_1-3-c-演化" class="header-anchor">#</a> 1.3.C++演化</h3> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210710141535846.png" alt="image-20210710141535846"></p> <ul><li>C++语言 (1983) 就有了</li> <li>C++ 98 (1.0)『语言真正正规化。是1998年』</li> <li>C++ 03 (TR1, Technical Report 1)</li> <li>C++ 11 (2.0)『过了13年才有2.0，中间有一些小的版本』</li> <li>C++ 14『2014年又有一个小版本』</li></ul> <p>​	本课程讲解：目前大部分在业界，大部分的程序员所使用的，其实大家不必太在乎版本。</p> <p>​	大部分所用的几乎都是C++98，2011的这个版本出现了很多新的关键字、新的概念、在标准库上也出现了很多新的工具、东西来用。也许太新了『<strong>本课程现在才2015年</strong>』，所以使用这个新特性的人并不是太多。所以，本课程讲解的都是C++最基础的东西，C++98就有了</p> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210710141746354.png" alt="image-20210710141746354"></p> <h3 id="_1-4-学习c-是学什么？『2部分』"><a href="#_1-4-学习c-是学什么？『2部分』" class="header-anchor">#</a> 1.4.学习C++是学什么？『2部分』</h3> <ul><li>C++语言</li> <li>C++标准库</li></ul> <p><font style="background:yellow;">『方法论』现在，几乎学任何一个语言，都是这样子的，要把这2个分开来</font></p> <p>​	在比较早期，也许在C的时代。大家还关注的是语言的部分。当然，你也脱不开，标准库的部分，C也有它的标准库。我要传达的概念是：现在语言越来越复杂，所以他们的标准库给大家的东西也是『越来越多』，那使用这些标准库，也是一些非常重要的一些事情。</p> <p>​	我们这门课：我们主要谈论语言，我们用到『标准库』，只有一些最简单的一些东西的输出。实际上，标准库是非常庞大，非常有用的。可以说：如果你是C++程序员，如果你不怎么去用标准库的话，你不能算是一个合格的、好的程序员、有生产力的。</p> <ul><li>当你发现：在学生时代/进入业界，开始大量的写你们的大型的语言的，你就会知道标准库的重要性。</li></ul> <h3 id="_1-5-书籍推荐"><a href="#_1-5-书籍推荐" class="header-anchor">#</a> 1.5.书籍推荐</h3> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210711162749553.png" alt="image-20210711162749553"></p> <p>​	课程开始前，介绍经典书籍，语言部分，上面是卖得最好、读者最多的百科型全书C++。经常，我们学1个东西，我们都要学习一下某某之父写的东西『就是右边这本』</p> <p>​	『左边的书《C++ Primer》，是<strong>C++第1个编译器</strong>的作者写的书籍』，所以也有相当的说服力。</p> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210712204753316.png" alt="image-20210712204753316"></p> <p>​	学了语言之后，其实很希望得到专家的建议。在这个里面呢，我也扮演这种角色，告诉你什么东西该写，什么东西怎么样写比较好。</p> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210712204818794.png" alt="image-20210712204818794"></p> <ul><li>刚刚，我们说完『语言』，语法和语义。</li></ul> <p>​	我们现在说『标准库』， 我也看过很多这方面的书，很推荐左边这一本。当然，深入下去，想看一下源代码，这种书就很少。右边，源代码解析。这条路很遥远了，不解释太多</p> <ul><li><p><strong>STL其实就是标准库的前身</strong>。可以想象标准库中，70-80%以前叫作STL『简单这样理解』</p></li> <li><p>只讲了这么点：肯定有遗珠之憾。</p></li></ul> <h2 id="✅语言部分"><a href="#✅语言部分" class="header-anchor">#</a> ✅语言部分</h2> <ul><li>『现在，咋们<strong>正式进入“语言”的部分</strong>』</li></ul> <h2 id="_02-头文件与类的声明"><a href="#_02-头文件与类的声明" class="header-anchor">#</a> 02.头文件与类的声明</h2> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210710142207614.png" alt="image-20210710142207614"></p> <ul><li>首先拿C和C++在『函数』和『数据』上角色的不同，进行比较。</li> <li>C语言中那样设计：数据和函数，这样的缺点：由于语言没有提供足够的关键字，所以这些<strong>数据一定是全局的，所以大家『所谓大家就是各个函数』都可以去处理它们</strong>，这样它们对后面会有影响的，甚至是很大的影响。所以发展出面向对象语言C++。<strong>C++是第1个最有名的面向对象语言</strong>，想法是什么呢？就是把数据还有处理这些数据的函数包在一起。你的数据只有这个函数才能去处理它。其他人看不到。这样不会混杂在一起，</li> <li>其实class也就是C中的struct结构。只不过，**C++使用了更多的特性在里面，使用了『更多的关键字』**让我们去使用这些特性。</li> <li>C++也有struct，几乎等同于class，它也引用一些很好的特性。『这两者之间有一点点和微小的差别』</li> <li>好：数据和函数包在一起。将来怎么使用呢？以这1个为类型，为1种形式，我们创建出很多对象。然后在这个对象里面，然后去创建</li></ul> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210710142525088.png" alt="image-20210710142525088"></p> <p>刚刚说过：对class的分类。最经典的分类：</p> <ul><li><p>1.里头带着指针『这个导致了，里头的指针，指向的内容在另外1个空间，然后「Big Three」</p></li> <li><p>2.里头不带指针</p></li></ul> <blockquote><p>『这个会影响后面的写法，<strong>影响深远</strong>』（重点知识）</p></blockquote> <ul><li>这1页，告诉大家，当你去思考你<strong>要设计1个类。它里面是有1个指针</strong>。你要非常小心。但是，我们现在要讨论的是没有指针的1个class这种先。</li></ul> <h3 id="_2-1-obp和oop模式的对比⭐️"><a href="#_2-1-obp和oop模式的对比⭐️" class="header-anchor">#</a> 2.1.OBP和OOP模式的对比⭐️</h3> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210710142633224.png" alt="image-20210710142633224"></p> <ul><li>对1个class的设计，我们举例『复数和字符串』</li></ul> <h3 id="_2-2-代码格式⭐️"><a href="#_2-2-代码格式⭐️" class="header-anchor">#</a> 2.2.代码格式⭐️</h3> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210710143019437.png" alt="image-20210710143019437"></p> <ul><li>在正式开始写程序之前。我们来谈一谈1个C++代码的基本形式：你会看到别人写的，以及你即将看到自己写的。</li> <li>头文件<code>.h</code></li> <li>主程序<code>.cpp</code>『主程序如何去使用头文件，就用<code>#include</code>方式，其实<code>.h是.cpp</code>的1部分，只是因为<strong>角色的区分</strong>，所以才把它分离开了。</li> <li>另外咋们的程序也可能会使用到标准库，<strong>标准库也是以头文件的形式提供的</strong>，用<code>&lt;&gt;</code>的写法，至于标准库放在你硬盘的哪个地方，你不用管，因为你在安装你的集成环境的时候，编译器有些步骤</li> <li>唯一的区别：
<ul><li>引用标准库的东西，用<code>&lt;&gt;</code></li> <li>引用你自己写的东西，用双引号『注意：面试时候的区别，不能光这么去答！』</li></ul></li></ul> <h3 id="_2-3-编程习惯-防卫式声明⭐️"><a href="#_2-3-编程习惯-防卫式声明⭐️" class="header-anchor">#</a> 2.3.编程习惯-防卫式声明⭐️</h3> <ul><li><p><font style="background:yellow;">guard，v.防范，n.防护装置</font></p></li> <li><p>大家写的任何1个头文件，都要写上一个，类似这样的<strong>防卫式的声明</strong>！</p></li></ul> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210710143449129.png" alt="image-20210710143449129"></p> <ul><li>写一个复数，应该放在头文件里面。</li></ul> <p>头文件的写法：有1种正规写法『这个1拿出去，大家一看，你是受过正规训练的』</p> <ul><li>Q：为什么要写这个东西呢？</li> <li>A：因为很多程序可能会用到你这个头文件，或者你自己的程序也分成很多文件，也可能会被<code>#include</code>用到这个文件。<code>#include</code>含进的<strong>次序</strong>，如果说要求用的人它必须，先includeA然后是B然后是C，那么这个对于使用者来说，<strong>负担太沉重</strong>。『对它而言，想要include谁都没关系，次序都没有关系。』所以，为了这样，我们要写1个防卫式的声明。</li></ul> <p>语法如下</p> <ul><li>代码解释：1进来，如果不曾经定义过这个东西的话。那么就把它定义出来</li> <li>第2次引用的时候，这个名词就引用过了，我们下面写的代码，就不会被进去。『这样就不会用重复的<code>include</code>的动作』</li> <li>一般初学者不会去考虑这个，但是未来进入<strong>业界</strong>，<strong>正式写大的东西</strong>的时候，要记得我刚刚说的话！</li></ul> <h3 id="_2-4-header（头文件）的布局⭐️"><a href="#_2-4-header（头文件）的布局⭐️" class="header-anchor">#</a> 2.4.Header（头文件）的布局⭐️</h3> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210710143824490.png" alt="image-20210710143824490"></p> <ul><li>写完，防卫式声明。中间1块，我们要放什么呢？我们分为0、1、2这样的3个部分。</li></ul> <blockquote><p>『最主要是1和2』</p></blockquote> <ul><li>『1』就是你要写的那个复数的『声明（<font style="background:yellow;">class declarations，类-声明</font>）』</li> <li>『2』就是你要写的复数的『定义（<font style="background:yellow;">class definition，类-定义</font>）』，这样讲不上很精准，但是可以这样理解。</li> <li>『1』和『2』写好之后，你可能要检讨一下，有些东西『必须在前面先声明过，于是才会写0这个部分』（<font style="background:yellow;">forward declarations，前置声明</font>）</li></ul> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210712204956474.png" alt="image-20210712204956474"></p> <p>​	<font style="background:yellow;">注意：有些**『函数』<strong>在此，在本体body中直接定义。但是你也可以不在这里定义，你把他们</strong>『全部』放在这里定义，OK。**</font></p> <ul><li><p>上面<code>opeartor+=</code>函数没有<code>{}</code>，只是1个『<font style="background:yellow;">声明</font>』而已</p></li> <li><p>下面2个函数，『<code>real()和imag()</code>』，有<code>{}</code>，是『<font style="background:yellow;">定义</font>』</p></li> <li><p>任何1个class，一定有个头（head）单独这1行。大括号<code>{ }</code>包起来的，这个叫<strong>class body</strong></p></li> <li><p>这里面，你就开始要去设计，我的复数应该要具备什么样的数据、我应该要准备什么样的函数，才能去满足，使用复数的人的需求，比如共轭复数，设计结果如上。</p></li> <li><p>然后，还有个奇怪的『friend』，你可能要设计另外1个类，另外1个单元，另外1个函数，说它要和它之间是1个朋友的关系。这些都是后面要提的</p></li></ul> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210712205022063.png" alt="image-20210712205022063"></p> <ul><li>模板是C++为了让你能避免重复，引出了解决这种需求的方法</li></ul> <h2 id="_03-构造函数-ctor"><a href="#_03-构造函数-ctor" class="header-anchor">#</a> 03.构造函数(ctor)</h2> <ul><li>constructor（ctor，构造函数）</li></ul> <h3 id="_3-1-inline-内联-函数⭐️"><a href="#_3-1-inline-内联-函数⭐️" class="header-anchor">#</a> 3.1.inline(内联)函数⭐️</h3> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210710145314082.png" alt="image-20210710145314082"></p> <blockquote><p>inline的概念：<font style="background:yellow;">什么时候会产生inline呢？</font></p></blockquote> <ul><li>1、你的函数<font style="background:yellow;">在你的class的『<strong>本体</strong>』（class body）里面<strong>定义</strong></font>，它就形成了这样1种『inline』</li> <li>2、如果在外头『定义』，它就不是inline『重要，重要』，然后你就<strong>只能使用在外头的函数前面加上inline</strong>关键字去建议编译器</li></ul> <blockquote><p>到底什么是inline呢？有什么好处？</p></blockquote> <p>类似宏一样，但不是完全一样，而是有它的特性，而没有它的缺点。总之：如果你的函数是个inline fuction会很好。会比较快，比较好<br>
当然我们想说：<font style="background:yellow;">那所有函数，我们把他们写成<code>inline function</code>，那就最好了，的确是！</font><br>
但是：有些function，即时你说它是inline，编译器也不把它做成inline，编译器没有能力把它做成inline。</p> <p>​	这个分界点在哪呢？简单的这样想：如果你的函数太复杂了，就没有办法inline，这对我们写程序的人来说，这有点讨厌。干脆我们全部让他inline就好了。『可以！』</p> <ul><li><strong>但是你的inline只是对编译器的一个建议而已，是不是真的变成inline，由编译器决定</strong>。『如上，PPT中那2个函数是inline 函数，但最终会不会变为inline function，不知道！』，但我们看那个地方，这2个函数是如此的简单，想必编译器是有能力把它变为inline。</li> <li><strong>注意</strong>：上头那个函数，是在本题的『外头，定义的，但是我在『外头，给它也写了inline』，告诉编译器，你尽量帮我inline。『注意：反正后面不在本体内定义的，我们可以加inline』</li></ul> <h3 id="_3-2-访问级别-access-level-⭐️"><a href="#_3-2-访问级别-access-level-⭐️" class="header-anchor">#</a> 3.2.访问级别(access level)⭐️</h3> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210710145557644.png" alt="image-20210710145557644"></p> <p>在1个本体当中，很重要的可以区分为某几大段。用什么样的关键字来区分呢？private和public</p> <ul><li>什么东西需要放为private的呢？当然是数据！因为我们希望，数据封装的，不要被外界任意看到，应该只有自己才能看到。</li> <li><strong>那么函数的部分呢？『也可以分2种，1种是要给外界用的，1种只是我处理私人事务的时候要做的』</strong></li> <li>其实有第3种，叫protect保护的，但我们在例子里面不说他们。</li> <li>上面的，访问区域段，可以任意出现顺序也可以交错</li></ul> <blockquote><p>好的编码习惯：</p></blockquote> <p>​	『<strong>注意，数据一定，要通过它们的兄弟，它自己的函数来传递出去或者被设定，1个读，1个写，不能那样直接被外部拿或者写</strong>』 除非，那个数据是public，但我们就是要避免这个事情！</p> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210712205151034.png" alt="image-20210712205151034"></p> <p>​	构造函数，是个大主题。</p> <p>​	C++这个语言说：如果你想要创建1个对象，1个东西，有1个函数会被自动调用起来，不需要你调用，它自动就起来。</p> <ul><li>1.有参数的创建对象</li> <li>2.无参数的创建对象</li> <li>3.动态的创建对象</li></ul> <p>​	构造函数，能写默认参数！这个没什么特别，其他的函数也可以写出默认值出来。<strong>构造函数特别</strong>的地方：名称、没有返回值类型『因为构造函数就是用来创建对象的，所以你不必写，你写，我还怕你写错』</p> <p>构造函数里面要做的事情：</p> <ul><li>1.设置到实部和虚部：可能在大括号里面写，这样OK，但是咋们要弄一个大气，好的写法是：不要这么写。<strong>我们应该要利用『构造函数』的1种很特别的语法，『只有构造函数才有，其他函数是没有的』</strong>——初始化列（<strong>initialization list</strong>）。初始化，这种写法，我会看你是不是充分使用。而不是省略的放在<code>{}</code>里面，最后结果是1样的，但是表示你没有受过良好训练</li> <li>初始化列（<strong>initialization list</strong>）和写在<code>{}</code>的**assignments（赋值）**的区别『简单说』，其实背后还有很多原理：</li></ul> <blockquote><p>PS『注意』：</p></blockquote> <ul><li><p>1个东西，它的数值的设定，有2个阶段。</p> <ul><li>1个是<strong>初始化</strong></li> <li>1个是<strong>后面再赋值</strong>。</li></ul></li> <li><p>第1阶段，就是我们的**『初始化列（initialization list）』**</p></li> <li><p>第2阶段就是在<code>{ }</code>里面去赋值。</p> <ul><li>如果你不在『初始化中做』而是在<code>{}</code>中写，表示你放弃了『初始化的那个阶段』，虽然最后你还是把值放进去了。实现得晚，效率也差一些。</li></ul></li> <li><p><font style="background:yellow;">注意：你不可能在你的程序里面去『<strong>直接</strong>调用你的构造函数』，这不可能，没有这种语法。</font>你只是要创建对象。而创建对象上面3个都是例子，这个函数就自然而然的调用起来。</p></li></ul> <h3 id="_3-3-class-『without』-pointers-members的特点⭐️"><a href="#_3-3-class-『without』-pointers-members的特点⭐️" class="header-anchor">#</a> 3.3.class 『without』 pointers members的特点⭐️</h3> <ul><li>此外：与构造函数对应的，有个析构函数，语法也蛮特别的。但是在我们这个例子里面，不需要写析构函数！</li> <li>原因：前面我们提到过，class有1个经典的分类，1种带指针，1种不带指针。<font style="background:pink;">这种就是不带指针的class，<strong>多半是不用写析构函数的</strong>，『也不能说全部哈！（whoway的想法是，之所以说多半是因为，比如需要某析构函数来输出提示文字帮助阅读，但是从内存的管理角度，是不需要写析构函数的）</font>』</li></ul> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210712205248623.png" alt="image-20210712205248623"></p> <p>​	『构造函数可以有很多个！』现实生活中常常会这样吗？常常会，比如你现在设计1个类，等待外界要来创建1个对象。创建对象的时候，要怎么创建，你可能有很多想法，比如你可能有3种想法：那你就写出3个构造函数。</p> <blockquote><p>重载：overload单词记住！大厂面试总是说英语术语。</p></blockquote> <p>​	上面的PPT，我们每次1和2组成一组！</p> <ul><li>Q：real函数里面的，1号取得值，2号设定值、这样写可以吗？？</li> <li>A：可以。因为函数可以重载，『注意，2号那个const肯定要划掉，因为是设定值。』
<ul><li>目前我们没讲const</li></ul></li></ul> <p>注意：可能很好奇，为什么同名函数可以1个以上，既然一样的名称，将来调用的是谁呢？</p> <p>其实编译器会把这些函数编成，右下角那个样子，只有编译器看得懂。</p> <ul><li>『注意点』<font style="background:yellow;">『易错』画黄色底色的，这种写法是不行的！『因为二义性』</font></li> <li>看起来语言上是可以的，但是实际上是不行的！</li> <li>原因：
<ul><li>因为1号有默认参数，我们创建代码中，1和2都是没有给参数，写法虽然不一样，但是意思相同。</li> <li>『左边的2里面没有参数，所以可以候选，而1呢，虽然有参数，但是有默认值，感觉也可以调用，</li> <li>编译器一看，2和1都可以调用，编译器会犯傻（也就是<strong>二义性</strong>！）</li> <li>『这种情况下，<strong>左边的2不允许被再写！</strong>』</li></ul></li></ul> <h3 id="_3-4-函数重载常常发生在"><a href="#_3-4-函数重载常常发生在" class="header-anchor">#</a> 3.4.函数重载常常发生在</h3> <ul><li>函数重载，常常发生在『构造函数』身上，注意上面那种例子的函数！不能那么写，因为冲突了</li></ul> <h2 id="_04-参数传递与返回值"><a href="#_04-参数传递与返回值" class="header-anchor">#</a> 04.参数传递与返回值</h2> <h3 id="_4-1-构造函数如果是private？⭐️"><a href="#_4-1-构造函数如果是private？⭐️" class="header-anchor">#</a> 4.1.构造函数如果是private？⭐️</h3> <blockquote><p>面试考点：放到private区域，面试常常和『<strong>单例模式</strong>，放在一起』</p></blockquote> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210712205341235.png" alt="image-20210712205341235"></p> <ul><li>传递啥意思？</li> <li>放在private区域的函数，表示这个函数是不可以被调用的！『被外界调用』</li> <li>注意：我们下面，外界说：我要创建1个这种对象，构造函数就要被调用起来，可是构造函数又放在private中，不可以被构造啊，，所以这2个动作都是不可以的！</li> <li>Q：那可见，不应该有人把构造函数放在private区域咯？</li> <li>A：也不是，既然提出来了，表示会有人这么做！什么情况要这么做呢？？</li> <li>『就是，我不允许被外界创建对象！』那这样，这个class有什么用？？？</li> <li>下面是一个经典的写法！</li></ul> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210712205411584.png" alt="image-20210712205411584"></p> <ul><li>这是1个设计模式！！最简单的1个设计模式，我们不懂没关系!</li> <li>但是设计模式中，有1个叫作“单例模式”，它就用到了我们刚刚所说的那一种，那一种写法『构造函数放在private中』</li></ul> <p>外界不能创建它。那么外界需要它的话，那么怎么办呢？</p> <h3 id="奇怪的问题：static莫不是为了单例模式而生的？"><a href="#奇怪的问题：static莫不是为了单例模式而生的？" class="header-anchor">#</a> 奇怪的问题：static莫不是为了单例模式而生的？</h3> <ul><li><font style="background:yellow;">我们观察到：我们是借助static成员函数突破class的访问级别，被全局访问，然后借助这个static成员函数，去访问private的构造函数，『神奇的思路』。</font></li></ul> <p>Singleton，你可能查字典查不到这个字。你可能查字典，查到Single。</p> <p>演化意思就是单例。意思是，我设计这个A呢，我只要一份，外界只能用1份，所以它才不允许外界重建，那么那一份在哪里呢？？『<strong>那1份在黄色的部分</strong>』是static的，我们还没有谈到static的特性。但我告诉你，它里头自己准备了一份自己。。各位看下面，<code>static A a</code>，，它的里面有个自己『然后，<strong>外界要的时候，不能够用那种传统的创建方式</strong>，，，』</p> <p>要通过<code>A::getInstance().setup();</code>这个</p> <p>『这里出现了目前没有学的语法，重点只是告诉大家确实有这样一种需求，把构造函数放在private中去』</p> <blockquote><p>构造函数讲完了，现在我们继续分析，在class的本体Body中，还有些什么要注意的呢？？</p></blockquote> <h3 id="_4-2-const成员函数？-奇怪的语法"><a href="#_4-2-const成员函数？-奇怪的语法" class="header-anchor">#</a> 4.2.const成员函数？-奇怪的语法</h3> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/C++OOP%E4%B8%8A_28.jpg" alt="C++OOP上"></p> <ul><li>函数这个部分，这一件事情是很多很多人会忽略的，包括你可能写了很多年的程序，你都会忽略。这个事情。但是它非常重要。『就是，<strong>在函数的后头加const，一定要加在这个位置哈：小括号()的后面，大括号{}的前面</strong>』</li> <li>『我现在要引导你去想一件事情：对class立面的函数，有分为会改变数据的和不会改变数据的2种。不会改变数据内容的，马上加上const。』所以，const函数的意思就是，我不改变数据的内容。</li></ul> <h4 id="_4-2-1-const加和不加的后果"><a href="#_4-2-1-const加和不加的后果" class="header-anchor">#</a> 4.2.1.const加和不加的后果</h4> <ul><li>注意：const要加的话，就一定要加！！！『三遍的重要』</li> <li>不加的话，会有什么样的<font style="background:yellow;">后果？？</font></li> <li>注意右边：</li> <li>可能写成，<code>const class名字 对象</code>和<code>class名字 const 对象</code>，意思是说：我这个对象或者说是变量的内容，一定是不动的，不可以改变的。『万一，我用这种对象去调用去调用它的成员函数，万一你没有写const会是什么意思？</li> <li>检讨：万一没加，而使用者会这么用，会产生什么后果，使用者的第一行的意思：我这个值是不可以改变的哦，我这个复数里面的2和1都是不可以改变的，然后，我要取得实数部分，逻辑上可以，但是如果忘记写了const，那这个函数的意思就是说：我这个函数可以会改变Data，使用者说，绝对不可以该，这个函数却告诉我说，我可能会改变。</li> <li>这是矛盾的，所以，<strong>编译器编译到这个的时候，就说不行</strong>！你这个调用不行，如果你没有写const的话，它会说不行！『这样，使用者是不是会愕然，大吃一惊，我有个实部，为什么我不能够打印它的数据呢』那就表示你这个复数class设计不好！</li> <li>复数是谁设计的？不就是我们嘛。我们设计不好，就是因为该加const就没有加</li></ul> <blockquote><p><font style="background:pink;">『很多很多人忽略这个很重要的事情』</font></p></blockquote> <ul><li><p>关于：const用来修饰这个函数，像这样，修饰变数，<strong>const用来修饰函数的这个主题呢，还有很多事情要讨论。不过目前这样就可以了，我们就可以继续下去。</strong></p></li> <li><p>我们这样写，就很<strong>正规『可能你会想，如果使用者不这么用的话，就不会出错啊，但是我们要想得更周全一些</strong>』</p></li></ul> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210712205509284.png" alt="image-20210712205509284"></p> <ul><li>这个主题，也是我们在判断，你写的代码，也许可以，你的程序也许可以运作，但是你有没有受过好的正规训练。『我会看123，某几个点，这个就是其中一个点，就是你参数的传递呢，是pass by value，，有没有用到pass by reference</li> <li>它的形式是这样的：</li> <li>解释by value和by reference</li> <li>黄色圈起来的，全部都是参数，任何人要调用他们的时候，都药把东西传进去，这个叫pass传递参数。</li> <li>&amp;这个符号，在这不是取地址的意思。</li> <li>『标题上：pass by reference (to const)，，标题上上，也<strong>可能不是const『就是我们PPT中的2-7这种情况</strong>』』</li> <li>『标题上说的3种情况，在这都出现了』</li> <li>By value，就是整包传递过去了。。这个value多大，它就整包都传递过去了。传的动作，其实是压到函数的stack栈中。</li> <li>By reference，</li> <li>『我们要养成习惯，尽量不要pass by value！！！因为怕传递得太大了』那这样的时候，我们怎么办？？过去C语言可以传递指针，，这包东西太大了，我传递个地址吧。所以，很快。。</li> <li>『然后，现在呢，我有一个东西呢，像指针，但是更加漂亮，C++的就是reference引用，，，引用看起来摸不着。。</li> <li>『<strong>给你建立概念：引用在底部就是一个指针！！所以，传引用就相当于传递指针那么的快，但是它的形式又很漂亮</strong>。。』</li> <li>『所以，现在建立一个<font style="background:yellow;">良好的习惯</font>——『你最好，所有的参数传递，你都传递引用』，尽量不要传递值』</li></ul> <p>这个时候，可能有人检讨了：如果传递的是一个char呢→如果你传引用的话，那不是更大？那我还不如单单传char，这个讨论是很细节的。</p> <p>这个说法是对的！<strong>你愿意想得这么细也可以</strong>。『但是如果给你个大范围的遵循守则的话，我愿意说大家，不管什么都传递引用』</p> <ul><li>PS：C语言的经验，指针传递过去，那边那个函数一旦修改，就会影响我了，因为，我们是传递指针。那传递引用也有这个效果！！是不是呢要的呢？有时不是。。</li> <li>『如果传递过去，只是为了速度，并不希望你改就该我，我可以传递refernence to const、、我传给你，但是你不能去修改这个内容。因为你一旦修改，就会影响我。<strong>如果你改了，编译就会出错</strong>！』</li></ul> <blockquote><p>结论：参数传递，<strong>尽量</strong>都传引用『当然，char啥的，随便你」</p></blockquote> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210712205536615.png" alt="image-20210712205536615"></p> <ul><li>延续前面的话题，用来作为返回值的传递。</li> <li>『<strong>这个地方很小，但是会影响到，C++程序的效率，为什么你会选择来学C++，多半是，你考虑到它的效率</strong>，它的效率比其他的面向对象语言，更快。所以，<strong>我们在每一个影响效率的小节上，我们都要注意：把它内化成，我们的习惯</strong>。』</li> <li>『<strong>现在说，返回值的传递，也尽量by reference』尽量的前提，当然是，如果可以的话</strong>。也有不少情况是不可以的！！在谈了这个主题之后的后面会出现。</li> <li>尽量的：是在可以的情况下！！什么是可以，不可以，我们在后面讨论！！</li></ul> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210712205608505.png" alt="image-20210712205608505"></p> <h3 id="_4-3-『友元』"><a href="#_4-3-『友元』" class="header-anchor">#</a> 4.3.『友元』</h3> <ul><li>我们身上的钱，任何人可以来拿吗？当然不行。。朋友可以来拿吗？看你在现实生活中如何定义</li> <li>『但是，在这个人语言里头说，朋友可以来拿『数据』』</li></ul> <p>private的数据，不想让外界任何人去取得我的。我们要的就是这种封装，但是对于特别的一种人，我网开一面，我是设计class的人。</p> <ul><li>朋友太多了，是不是会有困扰。显示不知道，但是在C++中强调封装。朋友的话，就打开一个封装的大门。。</li> <li>所以：用朋友的设计还是非朋友的设计，看你自己</li></ul> <h3 id="⭐️相同class的各个objects互为friends（友元）「记忆」"><a href="#⭐️相同class的各个objects互为friends（友元）「记忆」" class="header-anchor">#</a> ⭐️相同class的各个objects互为friends（友元）「记忆」</h3> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210712205631574.png" alt="image-20210712205631574"></p> <blockquote><p>结论：</p></blockquote> <ul><li>有一个问题，常常被提起，甚至于很多年工作经验的程序员，也会被提起。<strong>它可能在日常生活中已经习惯怎么写了，它知道这样写是对的，可是它解释不出来</strong>！！</li> <li>『上面的黄色部分函数：这个函数<strong>是处理另外一个复数。。。竟然是直接拿，没有透过函数</strong>』这不是破坏了封装性吗？也没有出现friend的字眼。个位整理一下，现在是什么情况？？</li> <li>很多个角度去解释：</li> <li>1、相同的class做出来的对象，彼此互为友元『解释了，这个行为看起来打破了封装，但是其实是成立的』</li> <li>2、有的人解释这个事情，不是用这句话。。也解释得通，但是我想这句最好。。</li></ul> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210712205710331.png" alt="image-20210712205710331"></p> <h3 id="『习惯』"><a href="#『习惯』" class="header-anchor">#</a> 『习惯』</h3> <ul><li>注意：</li> <li>1、数据一定放在private里面</li> <li>2、参数尽可能用reference来传，能不能cosnt看情况</li> <li>3、返回值一样</li> <li>4、在类的本体中，这些函数应该加const就要加，不然，使用者可能会报错！！
<ul><li>5、构造函数，有个特殊的语法，初始化列，那个要尽量去用它。</li></ul></li></ul> <blockquote><p>什么情况是不能return by reference?</p></blockquote> <p><strong>一个函数的操作结果，要放在什么位置上呢？？如果函数必须创建一个地方来让他放！『下面2种』</strong></p> <ul><li>1、如果返回的，是放在一个你<strong>本来已经有</strong>的空间上面。『可以传递引用』</li> <li>2、如果函数必须创建一个地方来让他放！这个东西，返回之后，生命消失了，<strong>『这个就不能return by refernce』</strong>『<strong>除了这种情况，我们都可以去传递引用</strong>』</li> <li>首先考虑引用→用引用可不可以呢？→决定</li></ul> <h2 id="_05-操作符重载与『临时对象』"><a href="#_05-操作符重载与『临时对象』" class="header-anchor">#</a> 05.操作符重载与『临时对象』</h2> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210712205809562.png" alt="image-20210712205809562"></p> <blockquote><p>操作符重载：：是个很大很大的问题、是一个C++的很大的特性！！</p></blockquote> <p>C语言中，如果你要对一个东西进行操作，一定是设计一个函数。事实上，在C++里面，操作符就是一种函数。是可以让你重新定义的！！这是它很大的一个特点。</p> <ul><li>先讲：操作符重载之1『等会有之2』</li> <li>1和2的区别：成员函数或者是非成员函数。</li> <li>『看右边：我们分析<strong>操作符是怎么被编译器所看待的！！！『重要</strong>』』</li> <li>二元操作符：我<strong>们通常会讲左数和右数。『编译器看到蓝色箭头哪一行，它会把符号作用在左边身上</strong>。。如果左边的这个东西有趣对这个符号做定义的话，编译器就找到了。。。把这一行就编译成要去调用那个函数。</li> <li>『我把它隐藏的东西挖出来给你。。』所有的成员函数一定带着一个隐藏的参数，这个参数叫作this。。</li> <li>『取这个名字的原因是：谁调用我，谁就是this』this是我们写代码不必写，也不能写，你写出来就错了。。</li> <li>『注意，这个this指针我现在把它显示出来放在第一个参数，一定是这样吗？？不一定，不同的编译器行为都不一样，有的会把它在最后一个参数去。反正我们写代码看不到，不影响我们写代码』但是放在哪里都无所谓，反正有这么一个东西。</li> <li>+=啥意思，右边加到左边身上去。『左边框框那样写的原因，相比是左上角的，其他地方也会这么用</li></ul> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210712205845871.png" alt="image-20210712205845871"></p> <ul><li>引用。黄色部分，return *this对象，但是<strong>接收端</strong>却用引用，这样对吗？『可能的语法疑问』<strong>『易错</strong>！』</li> <li>对的！原因**：用引用传递的好处：传递者无需知道接受者，是以引用的形式接收**。</li> <li>如果用指针传递：传递者必须知道现在传递的什么，要有个特殊符号。。</li> <li>设计：或许你说，左下角的，你可能会返回类型是void，好像也可以。如果使用者只有单个这么用，那当然可以。但是『使用者』可能会这么用连串的+=，所以，我们这个时候就不能返回void了</li> <li>因为，加完之后还要当成右值。『当使用者没有连串使用的时候，OK，如果连串使用的话，是需要另外思考的』</li></ul> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210712205917907.png" alt="image-20210712205917907"></p> <ul><li>本体以外的部分，要么是：类的成员函数外界定义，要么是：全局函数</li></ul> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210712205944769.png" alt="image-20210712205944769"></p> <h3 id="_5-1-『临时对象』重要"><a href="#_5-1-『临时对象』重要" class="header-anchor">#</a> 5.1.『临时对象』重要</h3> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210712210024224.png" alt="image-20210712210024224"></p> <ul><li>考量：他们返回的，为什么不是引用，为什么最优先考量的不是引用呢？</li> <li>『<strong>为什么绝对不可以？因为他们返回的必定是个『局部变量，』先前是没有那个东西的，是在函数中创建</strong>的』</li> <li>自己死掉了，外界如果引用，就用到了错误的东西。</li> <li>注意：不是说要在函数里面创建个东西吗？这里好像没有看到。这里有个特殊语法！！</li></ul> <h3 id="『临时对象特殊语法』"><a href="#『临时对象特殊语法』" class="header-anchor">#</a> 『临时对象特殊语法』</h3> <ul><li><code>tyname()</code>这种写法，在<strong>标准库中其实很常见</strong>到  !!『STL源代码中有？？』</li> <li>我们必须熟悉他们。。</li></ul> <div class="language-cpp line-numbers-mode"><pre class="language-cpp"><code><span class="token keyword">typename</span> <span class="token punctuation">(</span><span class="token punctuation">)</span>就好像 <span class="token keyword">int</span> <span class="token punctuation">(</span><span class="token punctuation">)</span>
    过去你习惯的是<span class="token keyword">int</span> i
    然后你去用这个i
    现在是不一样！！
    
    现在，我们的是<span class="token keyword">typename</span>直接加小括号，只不过里头有参数就是了。。
    <span class="token keyword">typename</span> 加上<span class="token punctuation">(</span><span class="token punctuation">)</span>就是要创建临时对象，，什么叫临时对象呢？？就是我临时才要的，我不想给他名称。。
    它的生命到下一行就结束了。。
    那么，下一行就结束了，而且没有名称，适合我们现在这样的用法吗？？适合。
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br></div></div><ul><li>『我们看右边，注意！黄色的部分，其实其实也是临时对象！！其实它的语法，就是左边！！</li> <li>『这个语法所谓<strong>特殊呢。。一般人少用，但是标准库用得很多！</strong>！』</li></ul> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210712210101450.png" alt="image-20210712210101450"></p> <ul><li>上面那个不是加号，『是正号！！』数学上表示一个的，就是表示正号。</li> <li>正号的，那个其实应该可以传回引用、。。标准库这么写，，为什么呢？？会写错吗？？</li> <li>标准库这么厉害的，会写错吗？？那个很难说。。。<strong>它比没有错，。只是写得不是最好的</strong>！！『下载习题，自行尝试，我相信是可以的』</li> <li>注意：<strong>标准库的那些很棒的人。他们所写的标准库，并不是圣经。不是说它绝无挑剔之</strong>处。。</li></ul> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210712210144391.png" alt="image-20210712210144391"></p> <ul><li>接下来</li></ul> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210712210212112.png" alt="image-20210712210212112"></p> <h3 id="『重载-操作符的特殊』『易错』"><a href="#『重载-操作符的特殊』『易错』" class="header-anchor">#</a> 『重载<code>&lt;&lt;操作符</code>的特殊』『易错』</h3> <ul><li>任何一个操作你都有2种想法，设计为<strong>全局（全域）函数</strong>or<strong>成员函数</strong></li></ul> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210712210301277.png" alt="image-20210712210301277"></p> <ul><li>既然，&lt;&lt;的重载，<strong>是把右边输出到左边身上</strong>！</li> <li>『<strong>cout&lt;&lt;会把&lt;&lt;符号作用到左边身上！是不可能作用到右边身上的！！C++的语法就没有这种作用到右边身上的这种语法！！</strong>』</li> <li>左边是什么？是标准库定义的一种东西，我们现在不去深究他们，你把他们想象是代表屏幕，要输出到屏幕上去。这个是标准库早就写好了，可能是10年前写好的，不可能认识你写的class，所以，对于『<strong>operator &lt;&lt;』读作『output operator</strong>』我们<strong>绝对不要把这种操作符写成一个成员函数</strong>！！『注意注意：这种特殊的操作符重载，你没得选，你只能选一种。。不能写成成员函数！！！就是全局的那种，<strong>原因刚刚告诉</strong>你了！』</li></ul> <p><code>operator &lt;&lt;</code>这个中间有没有空格无所谓！！</p> <ul><li>提过，C++和C语言都是free format，自由形式。你要加几个空格都无所谓！首先考虑传引用，看有没有副作用。可以要不要加const？因为os不可以改</li> <li>本来返回值或许是void可以，但你如果想得远一点，你的使用者如果是一种连串的输出。你就得引用了『<strong>设计者的角度，牛皮</strong>』</li></ul> <h2 id="_06-复习complex类的实现过程"><a href="#_06-复习complex类的实现过程" class="header-anchor">#</a> 06.复习Complex类的实现过程</h2> <ul><li><p>章节总复习。</p></li> <li><p>设计一个class的注意：</p></li></ul> <div class="language-txt line-numbers-mode"><pre class="language-text"><code>1、构造函数的初始化列表：不会用的话，可能训练不太精良，虽然最后结果可能一样。
2、函数应该要加const就加，万一该加没见，可能会有副作用
3、参数的传递，尽量referen ce，而且要不是const要考虑
4、return要不要refernce
5、『数据尽可能的放在私有里面，几乎没有例外啊！！！』函数绝大部分，要放在public，当然单例就，，
因为你的函数主要是被外界调用。
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br></div></div><ul><li>完整的范例程序是标准库写的，我拿出来，拿掉一些没学的，你得到的范例程序会多很多。</li></ul> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210712210336851.png" alt="image-20210712210336851"></p> <ul><li>在类的里面写出来『定义』的，已经是inline了，，你要写个inline去建议！！</li> <li>没有写出来的，我们可以让他是inline函数，如下，整个函数 的全名是<code>Complex::operator +=</code></li> <li>『至于+=的左边和右边，左边是作为一个隐藏的参数放进来，我们直观右边』</li></ul> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210712210404912.png" alt="image-20210712210404912"></p> <ul><li>下面</li></ul> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210712210430019.png" alt="image-20210712210430019"></p> <ul><li>设计全局函数，然后我们和谷歌想法一样设计为inline</li></ul> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210712210453996.png" alt="image-20210712210453996"></p> <ul><li>注意：红线的，尽量要避免！！！完全违背过去使用的习惯</li> <li>是可以写出来这样用！！但是使用者可能会很惊讶。。它不喜欢这样，它应该避免。『正是因为这样，操作符这种，只好把它写成非成员函数？？』『23分钟』</li> <li>**乍看置下：好像OS不会被改变，如果你基础不够的话。。其实它会改变，它的状态会改变。但是必须是有经验的人，或者是你必须去查手册才会知道。。。因此传进来的时候，**不能是consrt</li> <li>你将获得的代码</li></ul> <div class="language-cpp line-numbers-mode"><pre class="language-cpp"><code>complex<span class="token punctuation">.</span>h
complex<span class="token operator">-</span>test<span class="token punctuation">.</span>cpp
string<span class="token punctuation">.</span>h
string<span class="token operator">-</span>test<span class="token punctuation">.</span>cpp
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br></div></div><h3 id="『class之不带指针部分讲完』"><a href="#『class之不带指针部分讲完』" class="header-anchor">#</a> 『class之不带指针部分讲完』</h3> <ul><li>下面开始带指针的分类！！！</li></ul> <h2 id="_07-big-three⭐️『class-with-pointer-members开始』"><a href="#_07-big-three⭐️『class-with-pointer-members开始』" class="header-anchor">#</a> 07.<code>Big Three</code>⭐️『class with pointer members开始』</h2> <h3 id="_7-1-记忆3大函数：拷贝构造函数，拷贝赋值函数，析构函数"><a href="#_7-1-记忆3大函数：拷贝构造函数，拷贝赋值函数，析构函数" class="header-anchor">#</a> 7.1.记忆3大函数：拷贝构造函数，拷贝赋值函数，析构函数</h3> <ul><li>我们接下来要谈的是另外一个经典的例子，这个例子是里面带着指针的，那这种情况常发生吗？</li> <li>常发生啊，我要拿string字符串来作为我们讲解的对象。</li></ul> <p>标准库有没有一个字符串让我们也像刚刚一样把它拿出来分享给大家呢？那标准裤的是最有说服力的。
有，的确有，但不是我们后面要看的这一个，因为这个标准库的字符串写得太复杂了。
加上了很多的功能，这个是我们现在没有办法去讲解的。
所以我自己写的一个跟标跟标准库不太复杂，我们这是简单的版本，但是够用啊。
这事实上所有的人在刚开始构想的时候，一定是这样的构想啊，不会是想到标准库的那种写法，那个太过复杂。</p> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210710153858136.png" alt="image-20210710153858136"></p> <p>那我们现在想要做什么事呢？
我给大家的例子，测试程序是这样做一些非常简单的事情，我只打算在这里头做2个
创造出两个字符串，有一个是有初值的，下面这个。一个是没有出值的。
啊我们马上就要联想，要去想到字符串的构造函数怎么设计？它是呼应这2行</p> <p>这一行呢就比较特别的，这个意思是说我要创建一个String s3，以s1为初值，所以这是一个拷贝的动作!!</p> <p>以s1为蓝本，叫设定到s3身上，所以三跟一做完之后将是一模一样。</p> <p>这是一个拷贝，你要说克隆也可以啊，克隆跟拷贝，事实上我还真分不出有什么区别。</p> <p>好，拷贝好。
然后下面呢我把三这不算三丢到c二的去，所以我们势必也要写一个『操作符重载』可以应付这个事情。
好，又发生下面这个事情，这是什么？
我们一般口语会说s3等于s2，这个是不精准的。这其实不是等于，这个是assign，赋值的动作，所以我们应该说s2负值到s三身上啊，负值给s三。
所以负值完之后呢，左边跟右边必然是相等，这也是一个拷贝的动作。</p> <p>所以刚刚发生的这样是一个拷贝动作这样也是一个拷贝动作，但是他们的差别在哪里呢？？？
那个时候s3才第1次出现
这个时候是s3刚刚已经出现过了，现在是要被赋值。</p> <p>所以这个会引发对应的在字符串身上不一样的函数被调用起来，这个叫做拷贝构造！！！『因为他现在正在构造一个东西，所以叫拷贝构造。』</p> <p>等一下，这就是我们这个例子的重点啊，怎么去写字符串的去应付这个拷贝构造。
那这一个呢就是拷贝赋值，我们应该在左手边写，怎么写去应付去对付这个拷贝赋值。？</p> <ul><li>下面3个特殊函数『就是框框框起来的4个中后3个』</li></ul> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210710161002475.png" alt="image-20210710161002475"></p> <p>那难道前面讲的复数它没有拷贝构造跟拷贝赋值吗？也有。可是我们没有写他？？
好，这两个函数如果你没有写的话，编译器会给你1套这1套所做什么事情呢？？？
拷贝构造和拷贝赋值。
他所所做的事情就是很忠实的1个位，一个位，一个bits的一个bit的copy，你没有写，就有那么一份，
所以前面学的复述也有那么一份这种函数，我们要去我们到底要不要自己再写一份呢？
我们就要去思考——默认的那一套，编译器给的这一套够不够用？？
那你想一想负数有什么东西？？
负数有实部，虚部实，实部，虚部忠实地拷贝过去。很好啊，我再怎么写也就是这样子了！！！那就用变异器那一套吧。所以我们没有在写。！！！</p> <p>可是在这种带着指针的这一种上面，如果还是让如果还是使用编译器给的这一套拷贝构造跟拷贝赋值的话，会有『非常不好』的影响！！！！
你想想看啊，我现在有一个对象，它里头有一根指针指向另外一个地方，我现在呢，又产生新的对象，如果只是拷贝，那就是指针拷贝过来。
他们两个其实指到同一个地方去，这并不是真正的拷贝，后面有更详细的图来解释这个概念。『『浅拷贝。。』</p> <p>所以只要你的类class里头带指针，你一定要不能用编译器给的那个默认版本！！！！！一定要自己写！</p> <p>这样我们就知道了，我要发展出这一个string呢，我应该写哪些函数，我才能够呼应使用者这么的使用它。</p> <p>那现在要新增加的是下面这3个，这是先前不曾看过的，在复数，就那个例子里面不曾看过的，这个叫什么？
这个看起来这函数名称跟它跟类的名称也相同，所以这也是一个构造函数。
——但很特别的是，他接受的是他自己这种东西！！我再讲一次，他接受的是他自己这种东西，所以叫拷贝构造。
——这个是个构造函数，但接受的是自己这种东西，所以叫拷贝构造。
第2个这个呢这是一个操作符重载负值的动作！！特殊的地点在哪里呢？？？
他赋值右手边，这个唯一参数。这个是右手边，也『是他自己这种东西』！！！！所以这是拷贝复制，刚刚那个叫拷贝构造，这个叫拷贝赋值。
只要你的类带着指针，你一定要写出这两个函数！！
第4个函数这个名字很特别，是跟class名称相同，而且前面加一个波浪号，，波浪符号，这个叫析构函数！！！</p> <p>当他死亡的时候，这个虚构函数就会被调动起来。
所以新增加的是二、三、四，，有一些书籍把这个东西这三个呢叫做big three、big three这三个特殊函数。！！！『说的C++ Primer吧』</p> <p>我们不太理解，在西方文化里面，也许他们的big three是一个俗语？？
或者是一个谚语要去称呼什么啊不太理解，不过在技术书籍里面确实看过有这么一个称呼！！</p> <p>现在我们往下看，这几个特殊函数以及这个构造函数在这个例子里头要怎么设计???
好，这个就是它的构造函数，这是有一个。
有一个默认值进来一个指针。
呃这是从c以来就延续的一个概念啊，就字符串是什么？
就是有一个指针指着头，然后后面就一串后最后面会有一个零，这样的一个叫做结束符号。
一个字符串多长有两种想法，怎么设计啊？
一种就是我不知道多长，但是最后面有一个结束符号，这样我就可以算出来。
另外一种是后面没有结束符号，但是前面多一个长度这样的一个整数。
啊一种是前面有常数那个line长度，比如说十啦、十五啦。
一种是前面没有长度这一个数字，而后面有一个结束。
不符号。</p> <p>Pascal用的就是前面有长度的那一种设计法。
c和c++用的就是后面有结束符号的这种设计方法!!!!</p> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210710161307085.png" alt="image-20210710161307085"></p> <p>好，我们往下看。字符串。
一般而言，大家对字符串都会这样子设计，让字符串里面拥有一根指针，在需要内存的时候才去创建另外一个空间来放字符本身。
这是因为字符串里面的东西有。
大有小，有时候是空字符串，所以这样的设计就有种动态的感觉会最好，而不要在字符串里头放一个数组，说里面都是字符。那这个数组你要设定多大呢？
一万吗，还是一百还是三？</p> <p>所以我们会想要动用以一种动态分配的方式，因此我们就确定下来了这一个class的data它应该放在private里头，这个data应该是什么呢？哦是一根指针指向字符，这样就确定下来了。</p> <p>然后我们去想，ok，好，显然不能够用。编编译器所给呃给我们的那一套特殊函数，什么拷贝构造啦、拷贝负值啊负值啦，不能用那一套，
『『所以我们要自己写一套现在被我圈起来的。』』
这一套有什么东西？现在被我圈起来的四个，其中的第一个，这个名称跟它跟类的名称相同，所以这是一个构造函数。</p> <p>这我们已经学过构造函数的接口，该怎么去思考？像这一个接口是怎么样传进来？一个指一个指针啊对，默认给他零。我们的接口是这样设计。</p> <ul><li>所以强调一点，你的class如果里头有指针，多半你就是要做动态分配！！！！</li> <li>像这样，你既然做了动态分配，那么这个对象要死亡之前的前一刻，析构函数会被调用起来，你就必须在虚构函数这里面把你动态分配。被它的内存释放掉</li> <li>Big three啊，我们已经刚刚讲的构造函数算big three吗？不是!!!!</li> <li>记忆：内存泄漏（memory leak）</li></ul> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210710161438991.png" alt="image-20210710161438991"></p> <ul><li>拷贝构造函数</li> <li>copy assignment operator念起来也太长，写起来也太长，所以我就把它写成copy op=</li> <li>而这一块呢，两个指针指向它，也非常危险，因为将来你改a，d就跟着受影响。所以这一种叫<strong>浅拷贝</strong>!!</li> <li>那什么叫<strong>深拷贝</strong>呢？就是我们要去写的这个函数里头要做的事情。</li> <li>如上，深浅拷贝『面试考。。。！！！』</li></ul> <h3 id="_7-2-拷贝构造"><a href="#_7-2-拷贝构造" class="header-anchor">#</a> 7.2.拷贝构造</h3> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210710161525948.png" alt="image-20210710161525948"></p> <ul><li>拷贝赋值函数</li> <li>好，我们往下看啊，这一页跟你解释为什么你一定要写自己的一个版本。
我们来看看什么叫做深拷贝。</li> <li>Q1  这一个函数叫拷贝构造，为什么叫拷贝构造呢？？
这是一个构造函数，因为它的名称跟类的名称相同，所以这是一个构造函数。</li> <li>Q2  为什么叫拷贝呢？
因为他收到的参数就是他自己这种类型石头拷贝给石头。人拷贝给人，猪拷贝给猪，所以这个叫做拷贝构造函数。</li> <li>空间创造出来之后呢，把内容拷贝过去，这个叫深拷贝。</li> <li>如果你没有写这个函数，编译器给的那个默认版本，只有把指针拷贝过来，那个就是浅拷贝。</li> <li>那个钱拷贝也就是刚刚这一张图，这是我们要避免的。因为这样造成这一块内存泄漏，又造成这一块很危险，为什么危险？</li> <li>两个人在看同一个东西！！！这个叫alias，别名的意思，就这一块呢呃又叫a，又叫b，这个叫别名。</li> <li>你有一个名称是你的姓名，是你的学名，你在。
家里可能叫三毛，叫这个小华，这是你的小名，是你的别名。</li> <li>-那么在这个编程里头呢，别名是一件危险的事，要特别注意。</li></ul> <h3 id="_7-3-拷贝赋值函数『注意概念，非常容易错！』"><a href="#_7-3-拷贝赋值函数『注意概念，非常容易错！』" class="header-anchor">#</a> 7.3.拷贝赋值函数『注意概念，非常容易错！』</h3> <ul><li><font style="background:yellow;">可能，本来就有东西！！！</font></li> <li>拷贝赋值，这个概念。好，现在先听我这边讲，我要把这一边的东西复制到我的把我的右手先跟你看起来刚好相反哈，我的右手是你的左边，我要把一。
右边的东西赋值或者叫拷贝到左边身上来，我该怎么办呢？
1、这左右本来就都已经有东西了！！『核心，最容易被忽略的地方！！！』
2、我应该先把左边杀掉，清空，然后创建出跟右边一样大的空间，再把右边复制到我的左边身上。
3、我再讲一次，这两个本来就都有东西，我要先把这一个的原来东西清空，然后分配一块跟这边一样大的空间，然后把这边拷贝到这里来，这是很容易理解的。
4、那这就是这三个动作，先delete掉自己，因为这个赋值操作哈用法是这样，各位看到这样子。</li></ul> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210710163641769.png" alt="image-20210710163641769"></p> <ul><li>学习大家风范</li> <li>如果你有指针的话，那你要怎么写呢？经典写法就是这样，一、二、三。可是你看到前面还有一个动作，
这个要<strong>功力深厚的人</strong>才会写出这一块啊那你现在一起手就要有一种大家风范，你也要会写这一块。</li> <li>检测那里，比如，可能是啊因为指针的名称也许变动了啊，或者后将来我们要讲继承的概念啊。</li> <li>反正会发生，只是你看起来不像有可能发生，所以要去做检测。</li></ul> <h3 id="_7-4-大师风范-检测是否：『坑点』自我赋值-self-assignment-⭐️⭐️"><a href="#_7-4-大师风范-检测是否：『坑点』自我赋值-self-assignment-⭐️⭐️" class="header-anchor">#</a> 7.4.大师风范-检测是否：『坑点』自我赋值(self assignment)⭐️⭐️</h3> <ul><li><p>优点：如果左边等于右边啊自我负值的话，就直接return ，不做事情了。</p></li> <li><p>效率高。</p></li> <li><p>第2件事情是，如果你没有这么做，你现在这么做的话呢，刚刚的解释是效率高？？
但如果你根本没有想过这要这么写的话，你只写下面一、二、三好像也不会出错啊，<strong>所以只是效率的高低而已，是这样吗？</strong></p></li> <li><p><strong>不是不是</strong>，如果你没有写这两行，<strong>甚至于可能结果会出错，不只是影响效率而</strong>已，我们来看看发生什么事情。</p></li> <li><p>你看是这样，他一开始左跟右就是指同一个，事实上就只有一个了，我把它画成左边跟右边啊，世上就只有一个。
那赋值动作的第一件事情是杀掉，还记得吗？
我们再回头看一看，一、二、三里面的第一个动作就是杀！！！
假设你没有写上面这一块啊，我们正在讨论要不要写上面这一块，你没有。！！！
嗯好，<font style="background:yellow;">那你就接下来就杀掉你看第一个动作就把『唯一』的这个杀掉了。！！！神乎其技的一个坑。。。</font>
那下一个动作呢再回到刚刚这边来，第二个动作是要去看右边那个的长度。
已经不行了呀，已经不见了。</p></li></ul> <p><strong>结论：所以我们做一个整理，就是写这个自我赋值不只是为了效率，还是为了正确性，所以这个是非常重要的</strong>。</p> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210712210639595.png" alt="image-20210712210639595"></p> <ul><li>如果你没有写这一块，而你的使用者呢他也没有自我赋值，那也就算了，安全过关侥幸。
但如果他按他自我赋值的话，你的使用者自我赋值的话，你这边不写这一块是会错的，结果会出错。</li></ul> <h2 id="_08-堆，栈与内存管理"><a href="#_08-堆，栈与内存管理" class="header-anchor">#</a> 08.堆，栈与内存管理</h2> <ul><li>上一节：</li></ul> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210712210702154.png" alt="image-20210712210702154"></p> <ul><li>这是在我要讲解的最后一个有关于字符串的一个函数。这个在语法上已经没有什么特别的地方了。
呃，由于我们在测试程序里头想要对我们的字符串做输出，打印到我们的屏幕上。所以跟之前对复数的想法一样，我们也要写一个操作符的重载。这个叫output operator，也就是这个&lt;&lt;。那么这个思考方式呢呃跟之前完全一样，我们要准备这应该会要写成一个成员函数还是一个全局函数呢？
不可以是一个成员函数，因为如果把它变成一个成员函数字符串的成员函数的话，使用者在用的时候，那个方向会相反。那个cout会本来大家都习惯在左边，
现在变成在右边啊，这个是大家没办法接受的，所以一定要变成是一个全局函数。然后他的参数呢应该有两个。
左边那个是cout，也就是这个ostream。右边呢，现在我们的例子是字符串，就是这一个</li></ul> <p>其他的这个想法呢都跟先前一样。任何东西如果你丢给ostream 可以被他接受的话，那你在这个&lt;&lt;里面就直接这样子用好了。
现在我们这个字符串里面有没有什么东西是可以直接丢给cout而被他接受的呢？</p> <ul><li><p>栈和堆</p></li> <li><p>所谓stack（栈），所谓heap（堆）</p></li></ul> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210712215044905.png" alt="image-20210712215044905"></p> <ul><li>动态取得怎么样动态取得就是用new。</li> <li>new 这一种创建方式跟上一种创建方式的差别是。你可以在认程序的任何地方，以new 的方式动态或者这一块。
而你动态获得，你就有自己有责任要去对立着他，去释放它。现在并没有释放这个delete 的写法。</li></ul> <h3 id="_8-1-stack-objects的生命期"><a href="#_8-1-stack-objects的生命期" class="header-anchor">#</a> 8.1.<code>stack objects</code>的生命期</h3> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210712215119294.png" alt="image-20210712215119294"></p> <ul><li>stack object. 的生命其只要离开作用域。他的生命就消失了就结束了。结束的时候，他的吸构函数就会被调用起来。</li> <li>所以这一种叫做local object。又叫做auto object。</li> <li>叫auto 的意思就是因为他会被自动的。这边说自动的清理，意思就是他的吸构函数会自动的被调用起来。</li></ul> <h3 id="_8-2-static-local-objects的生命期"><a href="#_8-2-static-local-objects的生命期" class="header-anchor">#</a> 8.2.<code>static local objects</code>的生命期</h3> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210712215200390.png" alt="image-20210712215200390"></p> <ul><li>另外有一种东西叫静态staic object</li> <li>他的写法是这样，在scope里头，一个作用域里头，本来这是一个local 的对象，或者叫做一个auto的对象。
我们刚刚介绍了这个术语。如果在他前面加上这个关键字的话，那就是静态的static 的对象。
他的生命又有什么不同呢？</li> <li>他的生命在作用域结束之后仍然存在！！也就是离开这个大括号之后呢，他还在！！</li> <li>那么他的。析构函数就不会在这个时候被调用。那他什么时候被调用，一直到整个程序结束。</li> <li>这是这种静态对象的特性。
如果你需要这种特性，你就得这么写。</li></ul> <h3 id="_8-3-global-objects的生命期"><a href="#_8-3-global-objects的生命期" class="header-anchor">#</a> 8.3.<code>global objects</code>的生命期</h3> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210712215241682.png" alt="image-20210712215241682"></p> <ul><li>我们再往下看。还有一种对象叫全局对象。</li> <li>写在任何作用域之外的：你也可以说在全局作用域之中。啊，『任何大括号之外的。』叫做全局对象，那他的生命竟然叫全局或者叫全域作用域，全域。</li> <li>可见他的生命一定是。在很早在什么，在main更早之前就存在了。而他的生命在main结束之后，他才消失掉。他所谓的存在或消失，我们联想到的就是这个对象。这个object 的构造函数跟析构函数什么时候被调动起来。</li></ul> <h3 id="_8-4-heap-objects的生命期"><a href="#_8-4-heap-objects的生命期" class="header-anchor">#</a> 8.4.<code>heap objects</code>的生命期</h3> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210712215324099.png" alt="image-20210712215324099"></p> <ul><li><p>内存泄漏的意思就是你本来有一块内存，可是经过某些时间或某些作用域之后，你对他失去了控制。以至于你根本没有办法把它还给还给任何人，还给操作系统，</p></li> <li><p>这当然是不好的，因为内存是一个很重要而有限的资源。</p></li> <li><p>比如右上方：这个指针p在离开这个作用域之后，这个指针本身就死亡了。但是指针所指的那一块空间还在。这个就是内存泄漏。</p></li> <li><p><code>new：先分配memory，再调用ctor</code></p></li></ul> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210712215425387.png" alt="image-20210712215425387"></p> <ul><li><p>我得到了指针。这个new 呢被编译器转化为你可以想象啊，其实这个写法也非常接近现实。
我们不知道现实是不是所有的编译器都这样啊，不过。可以说绝大部分都变成这种情况。
new. 被分解为三个动作。
第一个就是分配内存。用哪一个函数来做这件事情呢？operate new.
老师好像在讲绕口令一样。
刚刚讲的是new。现在又调用。operate new.
现在告诉你，『其实后面这个蓝色的operate new，它只是名字比较奇特的一个函数。』
『这个函数的名称就是operate 空一格加new。』
c 加加提供了一个比较特别的函数。
这一个函数的内部做什么呢？我们其实是可以看到它的源代码的，我也看过了，告诉你他里面调用的就是malloc。
这是c 里面分配内存的函数。
所以new 切成三个动作的第一个动作调用这个函数，也就相当于调用malloc</p></li> <li><p>第二个动作是次要的啊，不是我们的主角。
第2个动作是什么呢？只是把第一个动作得到的指针，它是point to void。
但是我们当初new 的时候是要用负数。
pointer to complex
这两个形态不符合。
所以二把它作为一个转型。</p></li> <li><p>三呢？通过这个指针，刚刚二得到了这个指针。
调用这是什么？
这是一个。函数名称跟class相同的函数。
所以它是一个构造函数。</p> <p>好，那就符合语法书告诉我们的了。
第一，先分配内存啊，第二次转型，第三是调用其构造函数。</p></li> <li><p>谁调用这个函数，谁就是this『所以pc也就是这里隐藏的这个参数this</p></li></ul> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210712215449726.png" alt="image-20210712215449726"></p> <ul><li>你的语法书也会告诉你delete做的事情是先调用析构函数在释放内存。</li> <li>new</li></ul> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210712215548707.png" alt="image-20210712215548707"></p> <ul><li>delete</li></ul> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210712215606153.png" alt="image-20210712215606153"></p> <ul><li>我们开始讲这个秘密</li></ul> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210712215642279.png" alt="image-20210712215642279"></p> <ul><li><p>没有任何书籍来说他。是我去观察源代码，在观察执行结果之后得到的一个心得。这是很宝贵的一个分资源。</p></li> <li><p>还要带着两个，这里是说话的橘色呃，<strong>砖头颜色的这两</strong>个。这是什么呢？这个叫cooking。
呃，cookie 就是小甜饼干的意思。</p></li> <li><p>你现在要追一个内存好系统说那我付一个小甜饼安给你，就是这个口气。
它的作用。</p></li> <li><p>到52。在vc 底下呃，我刚刚。我记得题吗？我也忘记，我说了没有。这是在vc 底下，在其他编译器底下的内存分配。比如说GNUC私底下呢跟这个非常像痣，但是这个大小就不一定跟VC相同。</p></li> <li><p>精神是一样的。好，在vc 底下这个加起来等于52，vc 他给你的每一个区块，每一个内存块是。一定是16的倍数。这是有原因的，但是现在没办法提啊，所以每一块都是16的倍数。五十二不能除以十六。最靠近五十二的十六倍数是64</p></li> <li><p>所以这一块还要在填补一些东西进去，就是这里深绿色的pad 配的就是一个填补物。</p></li> <li><p>我在这张图上画。你得到一个两个double 的一块空间。
其实并不是这样。
其实是怎么样呢？
是现在这个图。
多得的这么多东西。
这不是太浪费了吗？
嗯。
<strong>但是是一种必要的浪费</strong>。因为以后回收的时候需要靠这些某些东西来顺利的回收。
对作业系统而言，操作系统而言。</p></li> <li><p>那么对于我们呃呃学生啊，刚开始学习写程序的，也许你不会进入调试模式。
你不会想要进入调试模式底下啊，你一般用的是release mode
那这样的话，把灰色的拿掉。
再算一次。复数有八个字节。两个double。
不需要加这个比八个黑的。
然后一定要加上下cookie，这是一定要的。
加完之后呢，八加四乘以2=16。</p> <p>十六。就说十六的倍数。所以不需要调整，不需要加上这个深绿色的pad。</p></li> <li><p>上下cookie 做什么用？最主要的是他要记录整块给你的大小。为什么要记住这个东西呢？
因为将来系统回收的时候。你只给他一个指针。他怎么知道要回收多大？
所以必须有在某一个地方记录这个长度。</p></li></ul> <h3 id="_16的倍数的使用"><a href="#_16的倍数的使用" class="header-anchor">#</a> 16的倍数的使用</h3> <ul><li><p>六十四的十六进位就是四零。40。
这边记录是四一。
为什么呢？他本来应该是四零。
四零。借用最后一个bit，it 最后一位最后一个bit，it 零或一来表现，我这一块是给出去还是？收回来。</p></li> <li><p><strong>为什么可以借最后一个bit 的来使用？</strong>
因为<strong>我们的这个都已经调整到十六的倍数</strong>。
十六倍数的话，最后四个bit 的都是零啊，各位想一想。
最后四个四个位都是零，所以可以借其中一个来用。</p></li> <li><p>在字符串呢？字符串本身之内还是一根指针。所以它的大小是指针的大小就是四。
我这里并没有按照同比例来画啊，请大家注意。但是我里面的这个数字是正确的。
这个是4。在<strong>调试模式</strong>底下。要加上<strong>灰色的</strong>。</p></li> <li><p>看看四十八是十六的倍数吗？
是。</p></li> <li><p>所以就不需要加这种深绿色的pad。呃，四十八。</p></li> <li><p>十六进位是三零。所以这边写的是三，应该是三零，但是它这一块给你了，所以写的是31这么写31。
如果你把它还给操作系统，这里就会变成30。</p></li> <li><p>如果你在。</p></li> <li><p>非调试模式之下，那就没有这个灰色的了，没有这个灰色的。那我们再算一次。你现在有一个字符串里头只有一根指针，所以它的大小是四个bug，四个字节。要加上上下估计四乘以二。加完之后是十二。</p></li> <li><p>十二要调到十六的边界。16的倍数，所以是十六。</p></li> <li><p>十六呃十六进位就是一零啊，所以这里是一零。<strong>给出去了所以是11</strong></p></li> <li><p>而现在告诉你，其实你真正获得的是。这么多。告诉你运算的方式。</p></li> <li><p>当然了，你不知道这些事情对于你编程并<strong>没有立即</strong>的影响。但是知道他这心中自有丘壑啊，我们会更能够更能够彻底掌握。</p></li> <li><p>现在谈一谈，如果分配的是数组array会怎么样</p></li></ul> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722140807162.png" alt="image-20210722140807162"></p> <ul><li>在调试模式底下要加上那个Debugger Header</li></ul> <h3 id="『核心』delete的析构次数-free大小"><a href="#『核心』delete的析构次数-free大小" class="header-anchor">#</a> 『核心』delete的析构次数+free大小</h3> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722140844945.png" alt="image-20210722140844945"></p> <ul><li>如果没有搭配的话呢，很多人都说会造成内存泄漏。现在来告诉你对，会造成内存泄漏。但是也许不是你想象的那种内存泄漏。</li> <li>那个3记录总是在的，我们无论调用【】还是没有，free函数还是能正确弄掉3个</li> <li>重要：<strong>主要是dtor析构函数的次数的区别！</strong></li></ul> <p>其实delete 会被拆为两个动作，刚刚已经提过了。
两个动作里面的第二个动作会把这一块删掉。
啊，这一块删掉，这一块删掉必须cookie</p> <ul><li><strong>cookie 是的确是有完整记录这一块</strong>。</li> <li>所以删掉这一块是没有问题的。</li> <li>不会造成内存泄漏。
这边写中刮号。或者右边这边没有写中国号，都不影响这一整块的番薯。
因为这一整块的大小就记录在这里。</li></ul> <p>没电。所以。虽然再三的告诫大家要搭配array delete 要这么写啊，不要右边这么写。
<strong>但是问题并不是出在这一块</strong>。
发生内存泄漏不是这一块没有发生热水器。
问题是出在哪里呢？出在于。你这么写的话，编译器才知道你要删除的是一个数组。
他才会知道，下面原来不是只有一个。
而是有三个。
那知道有三个他才知道要去调用三次</p> <h2 id="⏳09-复习string类的实现过程『ing"><a href="#⏳09-复习string类的实现过程『ing" class="header-anchor">#</a> ⏳09.复习String类的实现过程『ing</h2> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722140914805.png" alt="image-20210722140914805"></p> <ul><li>ctor和dtor</li></ul> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722140938343.png" alt="image-20210722140938343"></p> <ul><li>copy ctor拷贝构造函数</li></ul> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722141007366.png" alt="image-20210722141007366"></p> <ul><li>拷贝赋值函数copy assignment operator</li></ul> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722141035492.png" alt="image-20210722141035492"></p> <ul><li>你将获得的代码</li></ul> <div class="language-cpp line-numbers-mode"><pre class="language-cpp"><code>complex<span class="token punctuation">.</span>h
complex<span class="token operator">-</span>test<span class="token punctuation">.</span>cpp
    
string<span class="token punctuation">.</span>h
string<span class="token operator">-</span>test<span class="token punctuation">.</span>cpp
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br></div></div><p>​</p> <h2 id="_10-扩展补充：类模板，函数模板，及其他"><a href="#_10-扩展补充：类模板，函数模板，及其他" class="header-anchor">#</a> 10.扩展补充：类模板，函数模板，及其他</h2> <h3 id="_10-1-进一步扩展static细节』⭐️"><a href="#_10-1-进一步扩展static细节』⭐️" class="header-anchor">#</a> 10.1.进一步扩展static细节』⭐️</h3> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722141202806.png" alt="image-20210722141202806"></p> <ul><li>我们现在谈论的是基于对象的程序设计，也就是写单一的class。</li> <li>static是什么呢？我们可以这个小主题，好好来熟悉一下<code>this-pointer</code> <ul><li>『当你的程序在很多的class之间走来走去，你要对这个this指针有充分的了解，才能够做到这一点』</li> <li>『<font style="background:yellow;">黄色的this你可写，可以不写，如果不写，编译器会给你加上那一行</font>』</li></ul></li></ul> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722141225582.png" alt="image-20210722141225582"></p> <ul><li>class中静态的数据只有一份，所以我们什么时候，会使用这种静态的数据。
<ul><li>比如，银行的账号体系。『利率就应该设计为static』</li> <li>『静态数据的性质和什么时候要使用它。』</li></ul></li> <li>什么时候要使用静态的函数呢？
<ul><li>『静态函数的特征和一般的成员函数的特征。。。差别在于静态函数没有this指针。。可见它不能够像一般的成员函数那样去取，去访问去存取去处理这些对象里面的东西，因为它没有this指针。。</li> <li>那它做什么用？显然它——只能去存取静态的数据，，静态函数如果要去处理数据的话，它只能处理静态的数据、这是环环相扣的，我们体会一下。</li></ul></li> <li>所以我测试如下：</li></ul> <div class="language-cpp line-numbers-mode"><pre class="language-cpp"><code><span class="token macro property"><span class="token directive-hash">#</span><span class="token directive keyword">include</span><span class="token string">&lt;bits/stdc++.h&gt;</span></span>
<span class="token keyword">using</span> <span class="token keyword">namespace</span> std<span class="token punctuation">;</span>


<span class="token keyword">class</span> <span class="token class-name">solve</span>
<span class="token punctuation">{</span>
<span class="token keyword">public</span><span class="token operator">:</span>
	<span class="token function">solve</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
	<span class="token operator">~</span><span class="token function">solve</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
	<span class="token keyword">static</span> <span class="token keyword">int</span> a<span class="token punctuation">;</span>
	<span class="token keyword">static</span> <span class="token keyword">void</span> <span class="token function">demo</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
	<span class="token punctuation">{</span>
		cout<span class="token operator">&lt;&lt;</span><span class="token string">&quot;demodemo&quot;</span><span class="token operator">&lt;&lt;</span>endl<span class="token punctuation">;</span>
		cout<span class="token operator">&lt;&lt;</span>a<span class="token operator">&lt;&lt;</span>endl<span class="token punctuation">;</span>
	<span class="token punctuation">}</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>

<span class="token keyword">int</span> solve<span class="token operator">::</span>a<span class="token operator">=</span><span class="token number">999</span><span class="token punctuation">;</span>
<span class="token keyword">int</span> a<span class="token operator">=</span><span class="token number">777</span><span class="token punctuation">;</span><span class="token comment">//改成static int a=777;结果不变</span>
<span class="token keyword">int</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token punctuation">{</span>

	solve<span class="token operator">::</span><span class="token function">demo</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
	<span class="token function">system</span><span class="token punctuation">(</span><span class="token string">&quot;pause&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
	
	<span class="token keyword">return</span> <span class="token number">0</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

输出
demodemo
<span class="token number">999</span>
请按任意键继续<span class="token punctuation">.</span> <span class="token punctuation">.</span> <span class="token punctuation">.</span>

</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br></div></div><blockquote><p>易错：</p> <p>如果你class的数据是静态数据！！『语法上要注意』</p> <p>你一定要在class的外头，做这样一行动作！！这杨一行动作，有的人叫设初始化，设初值。因为往往会写成这样，会给一个值。。有的人叫声明。不过严格术语来讲，这个叫作定义。。为什么呢？一般我们说，写一行下来，会造成变量获得内存，这一行叫作定义。。所以在这个类里头说。。这个变量是静态的，这个只是声明而一。因为它脱离于将来产生对象，它是属于class的。</p></blockquote> <ul><li>无论如何，我们要记下来一点：静态的数据，在类class的外头要写这样一行东西！！『如何写呢？？如黄色部分，至于要不要给定初值，都可以。。。什么鬼、？？？』『我测试了一下』</li></ul> <div class="language-cpp line-numbers-mode"><pre class="language-cpp"><code><span class="token keyword">int</span> solve<span class="token operator">::</span>a <span class="token punctuation">;</span>
<span class="token keyword">int</span> a<span class="token operator">=</span><span class="token number">777</span><span class="token punctuation">;</span><span class="token comment">//改成static int a=777;结果不变</span>
<span class="token comment">//输出的999变成了0.</span>
<span class="token comment">//此外，如果不写哪一行，编译器会报错。。注意总结</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br></div></div><ul><li>此外：静态的函数，它没有this指针，所以它只能去处理静态的数据！！！</li> <li>『调用static函数的方式有2种，第一种叫作通过对象！！那就和一般的成员函数一样！！『但是，这个编译器不会给我们做this指针那啥，因为只是静态』</li> <li><strong>第2种就是，我没有对象</strong>，也许我的银行才开张，还没有人来开户，但是我的利率得先写』</li></ul> <h3 id="_10-2-进一步补充ctors放在private里面-单例模式"><a href="#_10-2-进一步补充ctors放在private里面-单例模式" class="header-anchor">#</a> 10.2.进一步补充ctors放在private里面+单例模式</h3> <ul><li><p>诉求是什么呢？就是我们写的一个class 只希望产生一个对象。</p></li> <li><p>你可以去想想在现实生活中什么时候可能会用到。那那么当你需要的时候，就要像这样来做。</p></li> <li><p>其实做法有不止一种，但是现在这种做法是非常好的。</p></li> <li><p>但是这个写法还不是最完美，我们来检讨一下。</p></li> <li><p>你虽然写好了这个a 如果外界都。</p></li> <li><p>没有需要用到。</p></li> <li><p>这个a 仍然存在。</p></li> <li><p>这个静态的a 仍然存在，好像有点浪费。</p></li> <li><p>所以<strong>更好的写法是这样子</strong>。</p></li> <li><p>这个仍然是那个对外的唯一窗口。get instance 这个函数静态的。</p></li></ul> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722141337097.png" alt="image-20210722141337097"></p> <ul><li>下面改善</li> <li>上一页static的a是在private里面</li> <li>刚刚我们的例子里面这边有一个静态的自己。</li> <li>现在不这么做了，把它放到这一个对外窗口这里头来，唯一的差别就在这里。</li> <li>我们现在改为：放在getInstance函数里面『带来的好处，C语言中：
<ul><li>现在这一夜静态的自己是放在这个函数里头。
这带来什么好处呢？
那你要回想一下，在c 里面就已经存在了一个函数里面，静态的意思是什么？
<strong>『只有』当有人调用到他。这一个东西才会出现才会诞生，才会创建。那离开这个函数之后呢，这个东西还在，这是过去c 以来就有的呃呃性质</strong>。</li></ul></li></ul> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722141254648.png" alt="image-20210722141254648"></p> <ul><li>所以写成这样之后呢。即使没有任何人要使用。如果没有任何人要使用这个单例的话，那这个单例就不存在。</li> <li>一旦有人用了一次，这个单例才出现。</li> <li>并且也永远只有这一份。</li> <li>这是<strong>非常好</strong>的一个写法。</li></ul> <h3 id="_10-3-进一步补充cout"><a href="#_10-3-进一步补充cout" class="header-anchor">#</a> 10.3.进一步补充cout</h3> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722141402373.png" alt="image-20210722141402373"></p> <ul><li>也许你有疑惑，为什么cout可以接受各式各样的类型的数据，你可以把整数浮点数、double 值字符串。是指标都丢给谁要的，他都能够打印出来，他怎么这么厉害呢？
是不是他对于这个output operate a 也就是小于小于这个操作服务有做了这么多的类型的重载，会不会是这样的？</li> <li>把证据找出来。这个就是cout这是标准库里面的源代码挖出来的，这个就是cout</li> <li>他是什么类型啊？在这里看到了这名字很长，我也不念了。<code>_IO_ostream_withassign</code></li> <li>那这个类型又是什么？我们往上看，看到他继承是ostream。</li> <li>好，所以我们可以简单的说，cout 就是一种ostream。</li> <li>然后我们去看o string 的定义发现：的确如我们所想象的。他做的这么多的&lt;&lt;的操作和重返接受哪些类型呢？这边有点点点，所以其实还没有列出完整。</li> <li>正是因为如此，所以cout 的才能够接受那么多种不同类型的数据，而且可以把它打印出来。</li> <li>cout的补充完毕</li></ul> <h3 id="_10-4-进一步补充class-template"><a href="#_10-4-进一步补充class-template" class="header-anchor">#</a> 10.4.进一步补充class template</h3> <ul><li>完了模板是一个很大范围的东西。但是我这边用简单的两张投影片，让大家理解最精髓的部分啊，其他更延伸出去的细部就不涵盖在没有涵盖在我们这个课程里头。</li></ul> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722141531721.png" alt="image-20210722141531721"></p> <ul><li>当然这里头很多小小的语法上的细节，我这里并不带到他，应该这不是没有完整涵盖在我们课程里头。</li> <li>啊，但是精神上这样已经足够了。</li> <li>用法是这样用。这样子其实编译器看到他会把上面这一段代码。
把鸡全部替换为double。这样就得到了一份代码。这阴气再看到下面这一行，又把上面的题全部替换为整数，又得到一份代码。所以等于这样两个写法，使用者这么用其实是。
两份几乎完全一样的这样的代码，只有这个t 呢不一样。</li> <li>所以有的人会说模板会造成代码的蓬帐，指的是：我刚刚讲的这种情况，代码的膨胀。</li> <li>但是这个膨胀是必要的呀，你就是你头像要放的是实部虚部是double 或者是不需不是整数，这就是两种情况，一定需要两份代码。</li> <li>所以这并不是并不是缺点。</li></ul> <h3 id="_10-5-进一步补充function-template-argument-deduction（引数推导）⭐️"><a href="#_10-5-进一步补充function-template-argument-deduction（引数推导）⭐️" class="header-anchor">#</a> 10.5.进一步补充function template+argument deduction（引数推导）⭐️</h3> <ul><li>argument，引数，『就是<strong>实参</strong>』啊，侯捷说的『引数推导/实参推导』</li></ul> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722141611163.png" alt="image-20210722141611163"></p> <ul><li><font style="background:yellow;">实参推导argument deduction. 这个是和类模板，很大差别的地方。</font>
我们在网上看一次类模板的用法。用的时候必须明确指出来，里头那个type要绑定，为什么</li></ul> <div class="language-cpp line-numbers-mode"><pre class="language-cpp"><code>Complex<span class="token operator">&lt;</span><span class="token keyword">int</span><span class="token operator">&gt;</span> solve<span class="token punctuation">;</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br></div></div><ul><li>但是<strong>现在是function template 不必明确指出了，本来在这里要有尖括号</strong></li></ul> <div class="language-cpp line-numbers-mode"><pre class="language-cpp"><code>min<span class="token operator">&lt;</span><span class="token keyword">int</span><span class="token operator">&gt;</span><span class="token punctuation">(</span>r1<span class="token punctuation">,</span>r2<span class="token punctuation">)</span>		这样的尖括号不需要
    <span class="token function">min</span><span class="token punctuation">(</span>r1<span class="token punctuation">,</span>r2<span class="token punctuation">)</span>就可以了
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br></div></div><p>不必指出来为什么呢？
因为编译器会做argument deduction 实参的推导。
啊，这个非常好，他就把我们推出来说OK
既然这个r1和r2都是stome
所以他就跑到右边来把所有的t 替换为stone得到了一个函数的版本。</p> <p>那那继续编译下去呢，编译去看，唉，这个T是stone，所以a 跟b 要比大小就是stone要比大小。
stone怎么比大小？嗯，编译器不知道。
那怎么办呢？
操作符重载
编译器去看这个小于这个符号是作用在b身上，而b，b 是一种T
t是什么呢？现在说要比的是stone</p> <p>于是编译器就去找这个stone，看你有没有定义operator &lt;这个函数。</p> <ul><li><p>如果你有定义，我这边就通过了。</p></li> <li><p>如果找不到这一个函数，那编译器边的这个地方就是说。『『我虽然帮你。找到了该调用这个函数，可是这个函数里面比大小，我不知道如何比大小。』』
所以这是互相搭配的，这个叫函数模板。</p></li> <li><p>这样的设计嗯合理吗？</p></li> <li><p>其实很合理。
比大小就是这个符号。<code>&lt;</code>
不管什么东西比大小都是这个符号。
至于这个符号作用在stone身上，作用在person 人身上，作用在animal 动物身上，该怎么去比大小。
设计这个比大小的人责任不在他身上，责任在设计stone class的这个人身上，或者是设计animal 设计person。</p></li> <li><p>设计各种class 的人的身上，他才知道怎么去比大小。</p></li> <li><p>所以『这样把责任分开来是非常好的』</p></li> <li><p>这也就是标准库里面的作为。</p></li></ul> <p>标准库里面有一大堆这种东西，七八十个。
就把这一种东西叫做algorithm算法</p> <h3 id="hacv疑问：类模板为什么不能自动推导数据类型？⭐️"><a href="#hacv疑问：类模板为什么不能自动推导数据类型？⭐️" class="header-anchor">#</a> HACV疑问：类模板为什么不能自动推导数据类型？⭐️</h3> <ul><li><p>参考<a href="https://blog.csdn.net/RAM_MAM/article/details/76910483" target="_blank" rel="noopener noreferrer">链接<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></p></li> <li><p>函数模板可以根据实参的类型推导。逻辑上无参的函数应该不需要模板类。类模板类型的自动推导，是因函数模板要编译两次，每次都会利用函数的重载生成新的函数。这些不同的函数就是根据函数的形参类型，形参个数，形参顺序确定的。所以根据实参可以推导出形参的类型，从来自动推导出函数模板的类型。</p></li> <li><p>类模板是抽象数据类型，类没有参数之说（构造函数的参数不是用于确定类的特性的参数），因此类是没有任何信息可以推导出应该定义什么类，因此必须明确的给出类型参数。</p></li></ul> <h3 id="_10-6-进一步补充namespace"><a href="#_10-6-进一步补充namespace" class="header-anchor">#</a> 10.6.进一步补充namespace</h3> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722141637856.png" alt="image-20210722141637856"></p> <ul><li><p>那么name space 到底是什么呢？
语法是这样，这是一个关键字。
你后面可以命一个名称，然后然后把你所有的东西都放到这里头。我们就说所有这些东西被封锁。叫封锁是太太严格了，被包装在这一个：命名空间/名字空间里头。
所以也许在一个公司里头，你发展的一些东西，你怕跟别人同名，那同名是不可以的。
ok 你自己先写一个name space，那别人也写一个n base，这样永远不会打架。</p></li> <li><p>好，那我们要怎么去用标准库里面的东西呢？</p></li> <li><p>第一种做法是最简单的做法叫做<code>using directive</code> directive，just the 命令。
这意思就是说我现在这么写啊，我现在要使用这一个命名空间，叫s td 的这个命名空间。这种写法叫using directive。等同于你把这个整个封锁打开，全部打开。从此呢你不用再写全名了，本来在s td 里面呢，它的全名要写成这样子s。</p></li> <li><p>2』或者是我要一行一行打开，因为这个标准库里面可能有可能有几千个东西，我不想一次打开，也许会造成我后面的混乱。那这一种写法叫做<code>using declaration</code>。using的声明。</p> <ul><li>他是一条一条的声明了。</li></ul></li> <li><p>或者是你都不打算这个你就是要非常规矩的把它的每一个的全名。部的名称写出来，那就是最右边这样子。
都没有用到using</p></li> <li><p>革命尚未成功</p></li> <li><p>同志仍需努力</p></li></ul> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722141703881.png" alt="image-20210722141703881"></p> <h2 id="✅『类和类之间的关系开始』"><a href="#✅『类和类之间的关系开始』" class="header-anchor">#</a> ✅『类和类之间的关系开始』</h2> <h2 id="_11-组合-composition-与继承-inheritance"><a href="#_11-组合-composition-与继承-inheritance" class="header-anchor">#</a> 11.组合(Composition)与继承(Inheritance)</h2> <ul><li><code>Inheritance（继承）</code></li> <li><code>Composition（复合）</code></li> <li><code>Delegation（委托）</code></li></ul> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722141735891.png" alt="image-20210722141735891"></p> <ul><li>我们现在已经具备了什么样的技巧呢？</li> <li>我们已经能够良好的写出单一的class，不管他有没有带指针，写法不一样。
他以后不在写法会考虑不太一样，但我们都能够应付了。
这种叫做基于对象的设计。</li> <li>对于像复数这样的类，或者像字符串这样的类。
他基本上也不会跟其他的class 其他的类发生发生关系。
但是再来我们要考量的一些比较复杂的问题的时候。
你就需要让类和类之间产生关系，这个就叫做面向对象的编程，面向对象的思想</li> <li>所以我们首先要探讨的是类根类之间有些什么关系。
有的书籍，有的人把这些关系呢探讨的非常的细微，简直到了<strong>人生哲学</strong>的地步。『2333』</li> <li>我认为我们只要了解这三种关系。就足够往下进行解决。所有我们想要对class和class之间让他建立关系，全部都可以做到。</li> <li>所以我们接下去要谈的是继承、复合、委托。</li></ul> <h3 id="_11-1-composition（复合）"><a href="#_11-1-composition（复合）" class="header-anchor">#</a> 11.1.Composition（复合）</h3> <ul><li>表示has-a</li></ul> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722141806257.png" alt="image-20210722141806257"></p> <ul><li><p>先找最简单的来讲。composition这个术语有很多其他的名称。</p></li> <li><p>那在这个课程里面，我就用composition，也就是复合。</p></li> <li><p>那对于我们比较刚开始接触的人呢，看这看这样可能有点不习惯。于是我把它。
换一个角度看画，把它替换进来啊，这个这可能替换进来就变成下面这张图。这样可能比较清楚一些。</p></li> <li><p>下面是『适配器模式』</p></li></ul> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722141835854.png" alt="image-20210722141835613"></p> <ul><li><p>我有1个不一定是1啊，我有n 个也可以啊，has-a这这样的关系。</p></li> <li><p>这一种关系早就存在了，在面向对象语言出现之前！！早就存在。</p></li> <li><p>我们回想一下c 语言的结构：</p></li> <li><p>c 的structure a little 头你就可以放里头放什么呢？放其他的结构或者放整数，放字符串，放什么什么什么，</p></li> <li><p>这些都是拥有composition的概念。</p></li> <li><p>所以这个早就存在了，我相信大家也很容易理解。</p></li> <li><p>『核心方法』我们画成图。我们要慢慢习惯用图来表现类和类之间的关系。</p></li> <li><p>尤其以后系统越来越庞大。你要用图来表现，而不是直接看源代码。当我们在做沟通的时候啊，要用图来表现。</p></li> <li><p>所以大家要习惯。</p></li> <li><p>我里头有其他的东西，所以我就画成菱形的黑色。黑色表示有东西。等一下会出现白色的那另外一个话题。
所以我们一看到这个图，我们就知道他要表现的是composition</p></li> <li><p>dequeue这个英语为母语的国家里头，都把这个念在dq啊，不是念dQ 这个我们要注意一下。</p></li></ul> <p>『设计模式』</p> <p>这个是我刚刚所说的，换了一个面貌出现。而说不定这个deque有一百个功能。
但是被包进来以后只开放了六个功能，我用开放这个字眼来形容，只开放了这六个，而且名字也可能换了。
在存在这种情况的话，这就表现出一个设计模式叫Adapter。什么叫adapter 呢？变压器就是一种代表。</p> <p>改造/适配/配接都叫adapter，所以用在这个地方就是这个东西已经很棒了，你手上已经有这个东西了，现在客户想要另外一个东西。
但是你手上的这个东西功能其实完全满足，只是名称也许不一样，接口也许不一样。
那我们就说：那我们来写一个adapter 不就好了，把它改造一下一下而已啊，只是把名字换一下。</p> <ul><li>Composition（复合），表示has-a</li></ul> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722141921641.png" alt="image-20210722141921641"></p> <ul><li>Composition（复合）关系下的构造和析构</li></ul> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722141946953.png" alt="image-20210722141946953"></p> <ul><li>既然我拥有你。我们两个我跟你是不同的class。</li> <li>你有你的构造函数我有我的构造函数。我也不能够越俎代庖的去，去做你你在构造函数所做的事情，我应该只关注我自己。</li> <li>所以他们的构造函数之间。是一个什么样的关系呢？这个标题说composition 之下的构造和析构有什么关系？</li></ul> <h3 id="记忆『container和component』"><a href="#记忆『container和component』" class="header-anchor">#</a> 记忆『Container和Component』</h3> <ul><li><p>由于是左边拥有右边，所以左边叫Container，右边是Component，Component就是元件、组件</p></li> <li><p>从内存的角度画是这样。我拥有你。那我当然比较大，就画外面这个你比较小就画成小的这一个。
构造的时候，外界要构造一个外部这个东西。</p></li> <li><p>注意黄色这一段。构造一定要由内而外构造，这样才基础才稳定。这是在我们人类的的生活的理念之中也是这样，习惯也是这样，你要做一个东西，如果他有内部有外部，当然是先把理念构造好了才扎实。</p></li> <li><p>所以c 加加也要表现出这种特性出来。</p></li> <li><p>所以模拟出这个动作啊。我要模拟这个动作，我就说构造函数呢，我就借借用这一个特殊的这个语法构造函数，有他的初值列</p></li> <li><p>红色的这个我要表现的就是外部这个构造函数去调用里面的构造函数。等到执行完了之后才做外部这个自己的事情。</p></li> <li><p>这个有个先后，我要<strong>强调的就是这个先后的关系</strong>。</p></li></ul> <p>为的是呼应这句话。
而这句话是我们人类经验里面觉得这样是对的。
构造要由内而外。
所以红色先执行。那这一段是谁做的？我们在写外部这个港片的，我们其实不管这个东西的。
是希望c 加加语言帮我们实现这个东西。因为我们觉得这样很合理，但我们自己不去写他。所以红色这一部分。
是『<strong>编译器帮我们加上去</strong>的。』</p> <p>析构</p> <p>虚构的次序就要刚好相反，就由外而内。你有一个东西，他有三层，你要吸构它的时候，当然是外面那一层剥掉在玻璃面。
快播。更里面，你不能直接把最里面的抽掉，一抽掉，整个塔塔下塌陷。
可以理解啊，这在人类的这个这个生活习惯上也是这样。</p> <ul><li>『这个要注意这一点』。</li> <li>好，但是也要注意，其实这都是编译器帮我们安排好了。我们现在这里有两个class，只要各自去管各自的构造跟虚构。</li> <li>至于这些次序呢，编译器会帮我们加嘛加代码。</li></ul> <h3 id="默认构造函数？？"><a href="#默认构造函数？？" class="header-anchor">#</a> 默认构造函数？？</h3> <p>这边提到默认构造函数，为什么？
呃，析构函数没有所谓默认啊，但是构造函数这边提到默认为什么呢？『因为红色的是编译器加的』
他要帮我们去调用内部的这一个吸构函数，他怎么知道要怎么调用呢？
也许内部这个吸构函数有两个，三个四个、五个编译器。不知道要帮你调哪一个。
所以他唯一能够做的说，『那我的行为是帮你调用默认了这一个』。
如果这个不符合你意的话。</p> <p>你就要自己这么写，你要在自己这个外部的构造函数里面，在这个位置上写，我要调用内部的构造函数。
对啊，什么参数你就要自己写。</p> <h3 id="_11-2-delegation（委托）-编程手法pimpl⭐️"><a href="#_11-2-delegation（委托）-编程手法pimpl⭐️" class="header-anchor">#</a> 11.2.Delegation（委托）+编程手法pImpl⭐️</h3> <ul><li>Handle/Body（<strong>pImpl</strong>）</li></ul> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722140652866.png" alt="image-20210722140652866"></p> <ul><li>第二种关系跟composition 组合复合也脱离不了关系。这个叫Delegation（委托）</li></ul> <p>这两个class 它是用指针指过来的化身图是这样。仍然用菱形的，但是是白色的，空心的表示是指针。
也就是说我<strong>左边仍然有一个右边，但是这个有有点虚。不是不是那么扎实，我只是有一个指针指向他</strong>。
至于什么时候才真的拥有右边，目前还不知道。只是指正，所以画图是这样。</p> <ul><li><p>这样的关系我们就叫Delegation（委托）</p></li> <li><p>有些江湖流派不把这样子叫做Delegation（委托），这个无所谓，只要我们双方说的清楚就好了。</p></li> <li><p>委托为什么叫委托呢？我拥有这个指针指向你之后。在任何一个我想要的时间点，我就可以调用你。
来做事情，把任务委托给你。</p></li> <li><p>另外一个术语，这一个名词有另外一个术语就很好，我觉得比Delegation（委托）更好。
叫Composition by reference。</p></li> <li><p>他也是拥有，他也是有东西，只不过他有的是指针，所以叫Composition by reference。
怎么不讲by poninetr呢？其实我们的课程以来，从前面一直以来。从来没有提过by poninetr这个术语。
那是因为<strong>在学术界</strong>里面不讲by poninetr啊，只讲by reference。
即使你用指针在传，我们也叫做by reference。</p></li> <li><p>这个就是重点啊，两个类之间什么样情况下得的可选，叫委托，就是用指针相连。
那用指针相连的话，他们的寿命就不一致哦。</p></li> <li><p>我这这个左边只是对外的接口。至于真正的实现都在右边做。当左边需要动作的时候，都调用右边的这个类的函数来服务。</p></li> <li><p>永远如此，左跟右永远是这样的关系。这一种写法。非常有名，叫做Pimpl（pointer to impratation）
我有一根指针去指向为我实现所有功能的那一个类，这个叫作pimpl</p></li></ul> <p>『它的另外一个名称叫作：Handle和Body，左边是Handle，右边是Body』</p> <p>在外界看到的字符串看到的是左边的这一个。</p> <ul><li>他为什么这么有名了？我这么强调。因为我们把所有的类如果都写成这样的话。左手边，对外不变。
右手边是真正的实现，我们可以切换了。</li> <li>我的意思是这个指针将来也可以去指向不同的实现类。</li> <li>这具有一种弹性，也就是说右边这边是怎么变动都不影响，左边，也就不影响客户端。</li></ul> <h3 id="编译防火墙"><a href="#编译防火墙" class="header-anchor">#</a> 编译防火墙</h3> <ul><li>客户怎么看这个字符串都不受影响，那太好了。
或者这一个手法又叫做『编译防火墙』。
左边永远不用再定义啊，要变成只是右边而已。</li></ul> <p>什么叫<strong>引用技术</strong>呢。剂量技术计算个数，就像现在这种情况。
有三个字符串都在用同一个hello。
就好比你现在创建了一个字符串，内容是hello，然后你做一次copy 再做一次卡比，这样就有三个完全一样的东西。</p> <h3 id="inheritance（继承）"><a href="#inheritance（继承）" class="header-anchor">#</a> Inheritance（继承）</h3> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722120020603.png" alt="image-20210722120020603"></p> <ul><li><p>下一个关系，第三种叫inheritance 继承。</p></li> <li><p><strong>有的人有误解。觉得继承才是面向对象</strong>。</p></li> <li><p>其他两种，嗯太简单了，过去就有了，composition，用指针来做的composition，或者是用实际数东西来做的composition。
太简单，以为这个才是面向对象，其实不是。
这三种关系，都是面向对象的一部分。</p></li> <li><p>我想其实我们上这个课呢，你手上一定还会有书。不可能用课程完全取代书籍。这时候你可以去查一下struct跟class 非常像。
在哪里自己去查!</p></li></ul> <p>我们的习惯用这种空心三角形来表现，呃，画法是要从子类下面，这个是儿子，上面是父亲嘛，从子类往父类，这画画一个空心三角形。</p> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722120020603.png" alt="image-20210722120020603"></p> <ul><li>这样就是一个继承的语法，那继承C++很你也可以说他设想很周到，给你三种继承方式，这是其中一种叫public。</li> <li>在其他的语言上面，比如说<strong>java 他也有继承，他就只有public，所以他不必写</strong>。</li> <li>那C++呢除了public 继承，还有其他private 私有的继承，还有protected 的继承。啊，有三种。但是最重要的就是这种public。</li> <li>使用public 继承就是在传达一种逻辑意义。</li></ul> <p>如果你用public 继承，你去写两个class 的关系是如此，但他其实不是将来在某一个时间点可能会出错。
也许不会出错，这要看有没有touch到那个特殊的情况。</p> <ul><li><p>这并不是继承的一个最有价值的部分。
那他有价值的在哪里呢？是他跟虚函数搭配这个最有价值。</p></li> <li><p>Inheritance（继承）关系下的构造和析构</p></li></ul> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722120158547.png" alt="image-20210722120158547"></p> <p>从内存的角度来看，就是子类的对象。里头有一个父类的。我喜欢用part 这个字眼——成分。
<strong>子类的对象里面有父类的成分在里</strong>头。这样的解释可能大家感觉更好成分。</p> <ul><li>于是这又是一个。外部里头包着一个内部的一种一种状态出现。
你回忆一下我们来回忆一下，这前面讲composition 也是这种关系。</li></ul> <p><strong>用代码来模拟</strong>的话，就是这样子。
子类的析构函数。
里头先把自己的事情做完，这个点点点做完了之后才调用父类的析构函数。
<strong>我们用这样来模拟编译器帮我们安插代码，是安插在什么位置</strong>。</p> <ul><li>请注意这边一句话。父类base class 的吸构函数必须是virtual</li> <li>要不然的话不会有下面这个好行为，下面有什么好行为，析构要由外而内。</li> <li>那这个原因原因讲起来比较大，比较长啊，我们现在<strong>先暂时这样理解，这个也是一个良好的编程习惯</strong>。</li> <li>只要你的class 是现在马上要让他变成一个父类，</li> <li>或者你认为将来他会变成一个父类，你就把你的析构函数设为virtual。</li></ul> <p>然后我们从内存的角度去探讨他在构造跟虚构的时候，这个外部内部是谁先谁后。
这个谁谁谁，随后我们已经不必操心了，是<strong>编译器</strong>已经帮我们完成了。</p> <h3 id="继承到底怎么用？搭配虚函数"><a href="#继承到底怎么用？搭配虚函数" class="header-anchor">#</a> 继承到底怎么用？搭配虚函数</h3> <p>我刚刚说单纯的从内存的角度去看，刚刚的那个例子只是为了。刚刚的例子只是做什么呢？
想要表现出子类对象比较大，因为它涵盖的父类对象里面的数据。
<strong>但继承主要不是这个用法，要搭配虚函数。</strong></p> <p>这个地方利用继承。目的只是为了。继承的关系：子类里头会有，父类里面是会有父类的一个part。</p> <h2 id="_12-虚函数与多态"><a href="#_12-虚函数与多态" class="header-anchor">#</a> 12.虚函数与多态</h2> <h3 id="_12-1-inheritance（继承）带有虚函数"><a href="#_12-1-inheritance（继承）带有虚函数" class="header-anchor">#</a> 12.1.Inheritance（继承）带有虚函数</h3> <ul><li>但是刚刚我有提到。当我们使用继承的时候，其实我们是要搭配虚函数来使用。才会达到。最强而有力的效果。</li></ul> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722120239291.png" alt="image-20210722120239291"></p> <ul><li>虚函数是什么呢？在语法上。我们只要在任何一个『成员函数』之前，加上virtual 这个关键字。他就成为一个虚函数。
在继承的关系里面，所有的东西都可以被继承下来。
<ul><li>数据可以被继承下来，就占用了内存的一部分。</li> <li>函数也可以被继承下来。可是函数的继承从内存的角度怎么去理解呢？不应该从内存的角度去理解！函数的继承，继承的是调用权。</li></ul></li></ul> <p>所以父类跟此类呢子类可以调用父类的函数，这个叫继承了函数啊，其实继承的是调用权。
所以这些所有的这是父类shape，是父类，这里面的函数子类通通可以调用。
那子类要不要<strong>重新定义</strong>呢？这就是我们现在要讨论的重点。</p> <ul><li>non-virtual函数，你不希望子类重新定义（override，覆写）它
<ul><li>这个重新定义这一个，在现在这个主题里面有一个术语叫做override。这<strong>个术语不能随便用，这个术语一定是用在虚函数被重新定义，才能够叫override。我们叫覆写。</strong></li></ul></li> <li>virtual函数，你希望子类重新定义（override，覆写）它，且它已有默认定义</li> <li>pure virtual函数，你希望子类一定要重新定义（override，覆写）它，你对它没有默认定义！
<ul><li>纯虚函数就是你希望子类去一定要重新定义它，不可以不定义。</li> <li>为什么不可以不定义的，因为你现在完全没有定义。</li> <li>注意这个位置啊，在这里等于零，那叫做纯虚函数。<strong>纯虚函数是没有定义的。其实纯虚函数可以有定义。但是在我们现在这个课程里头呢，我们就不去提他啊</strong>，其实它是可以有定义的。</li></ul></li></ul> <p>我把它设置为纯虚函数，意思是什么呢？
这个函数一定要被所有的子类重新定义，必须定义。因为什么？因为我现在作为父类，我根本不知道怎么去定义它。</p> <p>我们一个类里头。考虑到继承这件事情，
我作为父类，我的成员函数有三种选择，要怎么去思考呢？就是刚刚我所说的这一段。</p> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722120324781.png" alt="image-20210722120324781"></p> <p>好，所以继承这个关系，最终呢要的是搭配虚函数。
现在我来举一个非常经典的例子。
我使用powerpointle『PPT』。我举一个例子啊，我使用的是powerpoint。
当我要开启一个文件的时候，open file
我把这个菜单打开来选下去。
我现在是使用者。这边会跑出一个对话框。『右边』
里头可以条列出来，让我选择。
或者是我在下面这里打入file name文件名称。</p> <p>按下ok 之后，程序应该收到一个file name，他应该去检查发file name正不正确，有没有一些不可以有的字符。
然后他应该到硬盘里面去找这个file在不在。找到了之后把它open 打开来，打开之后把它读出来。
因为我这里要叫开启旧文件，所以应该把它读出来。</p> <h3 id="_12-2-template-method（模板方法）"><a href="#_12-2-template-method（模板方法）" class="header-anchor">#</a> 12.2.Template Method（模板方法）</h3> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722120350572.png" alt="image-20210722120350572"></p> <p>从刚刚左边的1二三四五六七这些动作。其实是任何人来写这段代码，写出来都差不多。表现出来的形式也差不多。
那何不有人先把它写好呢？能不能够有人先把它写好，让后面的人来用。
这些步骤理念只有最后这个步骤：就是开启文件之后的读物的内容。没办法事先写。
啊，因为我可能写一个简报软件，你写一个文书软件呃，他写一个试算表软件，我们最后要读出来要读的东西不一样。所以这件事情没有办法事先写好，
除此之外所有的都可以先写。</p> <ul><li>啊，于是有人就说那。那我们来开发这种产品好了，先帮大家把这些可以写的事情先写好！
啊，那么他就由于这个跟文件有关。好，就是他就写了一个class 叫做CDocument
Docunment里面有一个函数叫啊OnFileOpen
为了呼应我刚刚说，我们现在要对付的这件事情叫OnFileOpen</li></ul> <p>好，大家开始写了。这就是CDocument里面的OnFileOpen
他就把刚刚的一二三四五六七的动作全部写好。甚至于包括开文件，open file.
这个在整个在看你在哪一个平台底下，比如说你在windows 底下，你要开启一个文件，动作都是一样的。
这个写好之后呢，但是有一个动作他写不出来。
就是这个读的那个读内容的这个动作。
所以根据刚刚的说法啊，一个父类。有一些函数呢。没有办法先写出来。要让子类去写他。这一种我们就必须把它设计为virtual function方式。</p> <ul><li>纯虚函数是子类一定要去override 去覆写</li> <li>然后我们看怎么使用哦，这一个有一个团队他可能把这个CDocument写好了，而且他可以拿来卖钱，这一份。
我们把它买过来之后，这一块，我们写我们的子类。
注意这个时间点，他可能是1年前写好的，我们是现在才要写的。</li></ul> <p>我先创建一个子类的对象在这里。我通过子类对象调用父类的函数。
注意我这句话。在面向对象编程面向对象语言里面，这是一个非常常出现的动作。
通过子类的对象调用父类的函数。子类可以调用父类的函数啊，所以这个是没有问题的。
于是这一条我就用这一条灰色的粗线引导大家这一个动作呢，那调用的是谁呀？
这一个函数的全名叫什么？我子类并没有写这个函数哦。
但是我可以调用它。就这个函数的全名叫这样子。</p> <p>跑到我们写的这个函数来执行完毕之后再跑回去。然后才回到调用端。
完美。这正是我们所要的行为。这就是虚函数最重要的一种用途。</p> <blockquote><p>模板方法</p></blockquote> <p>这个做法是如此的经典，以至于有一个。『专属的名称。』
这一个函数它里头做了一些固定的动作。把其中的一个关键部分的延缓到子类去决定。
什么叫做延缓？你看这个，这个Serialize就是关键动作。
在父类是写不出来的，是一个斜体的表示抽象。延缓可能是一年以后，三年以后有子类把它写出来。
我们就把这一个函数。叫做，或者说这个函数的做法叫做template Method
大名鼎鼎的23个设计模式之一template Method。
不要误会template，C++也有template
但是这里不是C++的那个模板啊，这里是套用这个概念！！概念</p> <ul><li>Method是什么Method是java 的术语，java 语言说函数就是Method	。
所以其实这个就是C++里面的某一个函数。哪一个函数呢？
就是刚刚我们讲的这一个啊OnFileOpen
所以这一种用法你可以想象。对于一个做框架的人。
这边出现这个字眼framework，什么叫框架呢？
我先帮你想好了，你想设计一个应用程序，你该有哪一些功能？这些功能是差不多的。
因为在比如说在windows 底下所有的程序呃，左边菜单拉下来应该是怎么样，他的旁边应该是怎么样。
如果要开一个文件的话呢，应该出现一个对话框，然后应该怎么样？ 怎么样怎么样，这些都是固定的。</li> <li>大家写程序的竞争力,啊这个。这个拼搏的部分不在于这些一般性的动作上面，而是在于你的知识领域上！！
『所以这些一般性的动作谁来写都一样。那么就有人说来，我来帮大家把这个写好，这个叫框架，应用程序的框架。』</li> <li>那在这种应用程序的框架里面就会『大量』的用到了这种template Method 的手法。
也就是说，他就先把固定可以写的先写也好，留下那个它无法决定的函数呢。让他成为一个虚函数。让你的子类去定义它。
这一种框架当然是造福人类了。有人先把我们的写的一大堆东西都先写好。</li></ul> <blockquote><p>产品</p></blockquote> <p>有这么一种产品。最有名的在十多年前横扫全世界的一个产品叫MFC（ microsoft foundation classes）
就是这种产品。他所做的事情就是我刚刚所说的。</p> <p>虚函数的一个最经典最重要的一个用法。
你可能会很好奇，为什么这边走到这里来之后。他会跑到这个位置来。
我这边有一点补充，也许可以帮助你，但是这里面有很深奥的东西。
没有办法讲的非常的全面。</p> <p>我们看这一行。『刚刚已经为你分析过这一行调用动作，他的全名是这样。』
而谁调用我那个谁就会变成this pointer
所以如果我们扮演编译器的角色，我们把它写成这样子，这个MyDoc，这就是调用者他的地址就被放进来，变成一个隐藏的参数。
这个就是this。好，这一个函数，那就是这个函数呢。
这个函数就是这个函数，所以这个this pointer 就被传进来了，传到这里面来了。隐藏了，所以这边没写出来。
而这一个函数理念在调用函数其他函数像现在这样调用Serilazie 的时候，其实编译器是看成这样子。是通过类似来调用。</p> <ul><li>啊，真相大白了，this是谁？this是myDoc。myDoc就是这里啊。</li></ul> <p>我们用这一页很经典的例子来引导大家去了解继承搭配虚函数的最重要的用途。</p> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722120418341.png" alt="image-20210722120418341"></p> <ul><li>其实这个cdocument 当成是一个产品买来的，就文档上一定要写的很清楚。</li></ul> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722140525675.png" alt="image-20210722140525675"></p> <h3 id="_12-3-inheritance（继承）-composition（复合）关系下的构造和析构"><a href="#_12-3-inheritance（继承）-composition（复合）关系下的构造和析构" class="header-anchor">#</a> 12.3.Inheritance（继承）+Composition（复合）关系下的构造和析构</h3> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722140557393.png" alt="image-20210722140557393"></p> <p>我们继续下去。
现在有继承，前面有讲过复合composition，也讲过delegation 委托。
如果出现这种情况的话。又有继承，又有复合。在这种关系之下，构造跟析构会是一个什么情况呢？</p> <p>我们看看这张图。
这个就是父类和子类，而此类里头又有一个component。
从内存的角度去画。我们可以说。此类里头有父类的part 成分。又有component 在里头。</p> <ul><li>画成内存的角度这样。可是我应该先把父类画在上头，还是把component画在上头呢？</li> <li>不知道。但没有关系，我们只要知道这2个存在于这个子类这边的内容物就可以了。</li> <li>所以你可以想象，当你去创建一个这个Derived的时候。</li> <li>『问题』它的构造函数，应该先去调用，上面这个，也去调用右边这一个，可是谁先呢？？？？
这就是这个问号。这里的问号就是要问谁先。
这个先后其实影响不太大，对于我们后面写程序影响不太大。</li></ul> <p>不过对于我们主要是让我们能够深刻理解。那个内存的那个Layout布局。
我这里没有给你答案。我希望把这个留作你的习题。
你该怎么办？你就像这张图这样。写出三个类，建立起他们这一种关系，一个是继承的关系，一个是composition 复合的关系。
然后你在这三个类里头的构造函数，你都用cout打印出。打印出一个消息出来，你就可以观察谁先谁后。
啊，这个问号呢希望你自己来完成！！！</p> <ul><li><p>下面这种情况呢？这也是继承加复合，这个是继承，这个是复合。
我要回到上一页去。我现在回不去了，我看看啊。好，我用这一个。好，这个就没有疑虑了。
为什么这一种情况是子类里头有一个父类的part。
而父类里头父类的对象里头又有一个component 的成分在里面。所以画成图的话是子类这个最大。
里面有父类的成分，父类理念又有这个component 的成分。
所以他们的次序，那当然是：啊，当我要创建一个子类的时候，构造函数的次序当然是最里头的最先被调用。
那就是先component 在base 在drive。</p></li> <li><p>而虚构的时候刚好相反。
所以下面这个问号其实应该很清楚的，不用写代码，我们也在逻辑上推导的出来。</p></li></ul> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722115547405.png" alt="image-20210722115547405"></p> <ul><li>好，所以。进行到这里。面向对象程序设计。我们归类为class 跟class 有三种关系，我们全部都分别的把它处理完毕了。现在我要举几个例子，把这些实际应用起来。这也就是我们整个课程的最后的一部分。</li></ul> <h3 id="_12-4-inheritance（继承）-委托-delegation"><a href="#_12-4-inheritance（继承）-委托-delegation" class="header-anchor">#</a> 12.4.Inheritance（继承）+委托(Delegation)</h3> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722114612912.png" alt="image-20210722114612912"></p> <ul><li>在这三种关系里面，最====功能最强大的是这一种『委托+继承』</li></ul> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722114746736.png" alt="image-20210722114746736"></p> <p>比如这个例子。先给大家看一段这个在解决什么问题。我们看这一页。
啊，不晓得你有没有用过呃，powerpoint 或者word 的这种功能。我想所有的office 软件都提供这种功能。
你可以开一个呃。一个文件。并且在这个窗口这个地方，现在都是很小，在窗口这个地方呢。拉下来说，我要呃，
我现在忘记他的，他给我们的命令叫什么名字，应该是开一个新窗口吧啊那我就开了4个。
其实我这样的动作是什么呢？文件只有1份，窗口有4个。所以我等于是用4个放大镜或4个窗户在看同一个东西。
所有的office 软件都提供这种功能。不过呃，表现不太一样，像word 我就不太喜欢用啊。
word他开出来是没有办法像这样子排列，使得我在操作上。比如说我在写作，我在准备讲义的时候呢，就不方便使用。
但是在powerpoint这样子很棒的。或者是像这种情况。『指着右下角』
我有一份数据。就是一个document。我有三种不同的view，不是三个view，我是三种view</p> <p>再看他。要表现出这一种行为出来。就必须表现文件的这一种class。
还有呈现文献，一个是一个是储存数据，一个是表现数据。这两个class。之间要具备怎么样的关联性呢才能够表达这种状态呢？
这是什么状态？如果这里有变化，其他都要跟着变化哦。因为真正的Data只有一份。
这是什么状态？如果数据有变化，这些条状图，这些饼状图都要跟着变化。这样才对。</p> <ul><li>所以这是我们追求的目标。几乎所有写UI（ user interface） 啊，使用者接口uc interface。的程序员一定会碰到这种问题，你必须去解决这种问题。</li> <li>我们该怎么做呢？这边有一个非常经典的解法。我们设计一个class 叫subject，就是放数据，真正的Data的这里。</li> <li>我们在设计一个class 叫observer，就是去观察他的。也就是刚刚的那个窗口，有四个窗口要去观察它。</li></ul> <p>左跟右，我们让左边可以拥有很多个右边，因为使用者可以开出很多很多的observer 观察者。
所以我应应该怎么准备数据呢？在左手边这里，我们准备一个容器，现在选择的是向量C++容器
里头尖括号里头说我要放什么东西呢？我要放指针去指向右边这种东西。
这样就确定下来了，这是什么？这个就是带来可以选指针嘛。
而指向右边。我们前面有一个例子说左边是字符串，右边是字符串的实现。
当时我说那个用途不是非常大，因为左跟右是一对一，也不能变了，不能变化。
现在呢右边这一个可以被继承。
这个标题上的，委托加上inheritance ，这个继承在这里。
所以这只是一个父类将来派生下去有观察。
比如说按照1秒钟观察一次或者是什么情况，观察1次的。
这些下面这些子类全部都is-a，都是一种observer。
那既然都是一种呃，不知道吧，下面这些东西通通创建出来之后，都可以放到这个容器里头。
也就是说，『这有三种不同的人或三个相同的人在看这一份数据。』
回到上面，我们这个像这样就是相同的observer 有四个。
像这样就是不同的observer 有三个。
好，这样的话。就可以实现刚刚画面上所呈现的那一种结果。</p> <ul><li><p>我们的结论是。为了解决这个observer 这种事情，我们要写左边写这么一个class，而右边要写一个。父类，是这样。
左右是什么关系呢？对的，委托的关系，放的都是指针。
而右边，是一个父类必须可以被派生出很多的子类出来。</p></li> <li><p>继续往下讲。作为这个内容物应该提供一个『注册跟注销』的动作。你们谁想要来观察我，你们再来跟我注册啊。
所以这边应该要提供一个函数叫attach 名字随便取啊，现在这个例子叫attach。要附着谁呢？
附着observer 这种东西，所以这就把它放到容器里头。</p></li> <li><p>这个容器现在在这里叫m_views。还应该有注销的功能，但是这里没有呈现出来。
比如说我是设计一个电子报的人啊，我允许被登记被注册，我允许注销。还应该有一个函数叫notify。
说什么？把所有这个观察者放在这个容器里头，所有的观察者都寻便利啊，寻访一遍，去通知他。
那通知他这个动作要怎么完成，这就是双方左右要说好，右边要说我有一个函数叫什么，呃，叫a 好了。
那左边说我要调用a。不过这个a 呢在工业界都把这个a 这个函数我刚刚随口说的。都把它叫做OOD
『这个函数是这样才有意义，我要通知所有的，你们说啊准备更新数据。』
这个就是Observer，我们现在在进行是面向对象的设计。
而面向对象里面，我们就要考虑需要准备些哪些class 呢，能够解决某一个问题。</p></li> <li><p>现在要解决。刚刚画面上的这一种问题的时候。我们思考的结果是要准备左右这两个class。
之间要具备刚刚我所说的这些条件，这些关系就解决了这个叫面向对象设计。</p></li></ul> <p>所以在谈到这个od 啊面向对象设计。啊，最经典的就是世界上有一些很好的例子，呃，很有名的就是二十三个设计模式。我们现在就拿出我就拿出最容易被理解的这个例子呢来。
那来做解说。好，我们喘口气。接<strong>下来还要进行另外的一些很有名的设计模式</strong>。</p> <h2 id="_13-委托-delegation-相关设计"><a href="#_13-委托-delegation-相关设计" class="header-anchor">#</a> 13.委托(Delegation)相关设计</h2> <p>那我刚刚提到。到了有一些问题以及一些解法呢出现了有adapt这个关这个名称，有呃kindle body或者叫做policy in promotion这个名称。
我们有看到了呃technology、message这个名称，这都是代表一种问题以及一种解法。</p> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722114832031.png" alt="image-20210722114832031"></p> <h3 id="_13-1-composite模式"><a href="#_13-1-composite模式" class="header-anchor">#</a> 13.1.Composite模式</h3> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722114918779.png" alt="image-20210722114918779"></p> <p>也许你会想说，我可能还是个初学者，我才刚开始从单一的class开始学习起，突然就把我带到了设计模式。这这个会不会太快、太可怕，你觉得会吗？</p> <ul><li>当然每一个设计模式里面还有很细微的部分我们也并没有去提，他主要就是让大家了解怎么去组织你的类，用现实生活、现实意义的问题来做引导。</li></ul> <p>好，我们继续下去。现在如果我面对的一个问题是要请你写一个file system。呃文件系统。
或者请你写一个window system。我们怎么来思考这个问题呢？
window窗口系统，你现在打开你的电脑桌面，不管是哪一个窗口平台，
window平台都是大窗口里面有小窗口，小窗口里面可能又有一些小窗口。
那如果是你去想你的file system，你可以想到的是有文件有目录，
目录里面可以放文件目录，还可以看其他的目录，结合在一起，再放到另外一个目录里头。
现在我们面对的就是这一种奇特的形式问题该怎么办呢？
我该准备哪些class才能解决这些问题？
我该使用哪一些武器把它们关联起来？
非常经典的一个一个一种状况。</p> <p>我们看看，就以file system来讲好了，我认为我需要写出一个代表file的class，这里我把它叫做Primitive，也许我命名叫file文件会更具体一些，不过现在的命名是比较泛化的。
Primitive就是基本的，就个体单个体它不是组合物。
另外我应该准备一个class，叫做Composite，Composite就是组合物，就是合金。
好，我们开始思考，作为Composite他应该是。一个容器，因为它应该可以容纳很多个。
好，他应该可以容纳很多个左边Primitive这种东西。
但是这个问题是如此特别，以至于他还应该可以容纳他右边Composite这种东西。
哦我们有一个容器，必须可以放左边这种，也可以放右边这种，怎么办呢？
当我们要选C++的容器来用的时候，我们要声明，就好像这样子，这个Composite里面有一个容器，我们要去声明他，该怎么声明才好呢？
它又可以放左边，又可以放右边。
啊我们决定如果我为他左跟右写一个父类的。</p> <ul><li><p>我们发现在很多的经典的问题里面，经典的解法都是要用这两把武器。
这样的一个结构，或者说这个结构所要解决的问题。
呃这就是一个解法，我们就把这个解<strong>法叫做Composite，又是23个设计模式里面的一个</strong>。</p></li> <li><p>我们只要把刚刚分析的过程的这些结果呢写成代码。就是上面的PPT</p></li></ul> <p><strong>好，鼎鼎大名的Composite设计模式就是靠这三个class的合作而完成的。</strong></p> <h3 id="_13-2-prototype（原型模式）"><a href="#_13-2-prototype（原型模式）" class="header-anchor">#</a> 13.2.Prototype（原型模式）</h3> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722114955092.png" alt="image-20210722114955092"></p> <ul><li><p>我们再往下看我举的最后一个例子。</p></li> <li><p>我这个题目说,我需要一个继承体系、树状继承体系，还有r k?我想要去创建未来才会出现的子类，怎么办？
这个我，在这张图表现出来就是这个破折线，上面就是抽象的部分，就好像我现在在设计一个框架
，这些子类是未来才会派生下去的，是被客户买去之后他才派生子类，这个时候那个class名称才出现，而我可能是三年前写的这一段。
我不知道未来的class名称是什么，那我怎么去创建它呢？
不可能，我也不能够去读到一个字符串，然后说这个字符串里面是个class名称。『这个奇思妙想，我也以前想过HACV』
然后我利用这个字符串不行，new的后面一定要加class name。
那个classroom name现在还没有出现，那怎么办呢？</p></li></ul> <p>有一些聪明人想出了一个办法，说可不可以让下面派生的子类。
你们都创建一个你们自己，当成原型Prototype，让这个我，主角——框架这一边，有办法去看到你们创造出来的这些原型
放在什么位置上，我反正就可以看到它，这样我就可以复制它，就等于我在创建了。</p> <p>我再提一次现在出现的问题。其实不只是，所以这个叫Prototype。
这里所呈现的啊。『在其他的设计模式里头也会出现这种问题，就是我现在要去创建未来的class对象。』</p> <p>怎么办呢？那这是一个解法，Prototype说，好，你们后面发生的子类，你们自己去创建一个出来，
反正只要你创建出来的东西是可以被我框架这一边看得到，那我就可以拿到他呢，当作一个蓝本，我就copy我就可以copy很多份。
这样的解法，啊问题已经出现了，是未来的class名称，这是问题。现在没现在没有这个class名称，那解法是什么？就是我刚说的
你们每一个人都先创建一个给我。</p> <h3 id="static牛皮啊，hacv注"><a href="#static牛皮啊，hacv注" class="header-anchor">#</a> static牛皮啊，HACV注</h3> <ul><li><p>我们就拿一个来讲，我『在这个class里面安排一个静态的对象，我怎么在这个地方能够说它是静态的呢？』</p></li> <li><p>『<strong>这一种图的表现方式如果有下划线的话，这就是一个静态。</strong>』『记忆，记忆』
我们等于说用图来写代码了，这是一个静态。
为什么说他是自己呢？对，这就是我要的，我故意就是要让他是类，这class自己，所以它的类型是在这里就是LandSatImage就是这一个。</p></li> <li><p><strong>之前也没有提过这一种画法啊。跟大家说一下，我们写源代码的时候是先写类的名，呃typename name，再写object name</strong></p></li> <li><p><strong>可是画图的时候刚好相反，先写object的名称，变量的名</strong>称。</p></li> <li><p>刚好相反跟写代码刚好相反啊那这个地方是静态的，所以每一个子类如果都写这样的话，他们就自己创造了自己，这就是所谓的原型。</p></li> <li><p>而这个原型必须登记到被这个破折线以上，就是也许一年前或十年前以上写好的框架端看要能够让他看得到你创建出来的你。</p></li> <li><p>未来三年之后才创建的东西，要能够被他之前看得到。
那怎么办呢？应该由它上面这里准备一个空间，你下面这些人呢把你的原型放上去，放上去是属于上面的空间，上面当然就可以看到，去做处理。</p></li></ul> <p>所以我们下面打算这么做。这个静态的自己创建出来的时候，会调用起构造函数，这是我们所知道的这个语言规则。
『这个构造函数呢我把它写为private，在这里我怎么在这张图能够说它是private呢？
因为它是负的，负的代表私有的private，正的代表public』
那正的等于是默认，所以正的不写。』
#井号呢这边出现井号，这就是protect。</p> <p>如果没有这个原型的话，就没有办法通过对象调用函数调用克隆函数。
那你说那这样的话，如果我不要原型，我让这个clone是一个静态函数，那不也是调用得到吗？
不需要。通过对象就能调到他，他是个静态函数啊。
想一想，静态函数的调用一定要——class，name
可是现在讲的情况就是未来3-5年发生的新的class</p> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722115035422.png" alt="image-20210722115035422"></p> <ul><li>基本的观念就是这样，prototype。
问题所在，问题在哪里？这个刚才已经提过了，解法有多少种？
一中以上，但是这一种是非常精巧的一个做法，太令人拍案叫绝的一个做法。
那讲到这里必须提一下，这是谁写的？这不是我写的，这是。
等一下，我们马上要开源代码，要尊重原作者。』
这边这本书。哦这个书名叫Design Patterns Expained Simply
在这里面啊，各位也可以到网络上找到它的官网，他的例子都能够在网络上下载。</li></ul> <p>大家看着这一张画面，感受一下这个project的问题解法。
我们反省一下，那这么说是不是下面这些子类就带着一种任务、一种负担呢？
我们叫开销。overhead，什么样的开销？
本来不知道这个事情的时候，我自由自在的派生
争执了一下去写东西，现在呢却告诉我说，『我必须像这样要有一个静态的自己，我必须写一个私有的构造函数』，
我必须写一个clone函数，这就是我的负担，这样合理吗？</p> <p>你加注于我身上这种负担合理吗？</p> <p>答：合理。为什么呢？
世<strong>界上没有白吃的午餐啊</strong>，你要搭配这种人家事先写好的框架的部分，他事先写好了，你又又要让他知道，
你你一定要有一些额外的开销，这只是一种做法，在其他的做法上面呢我们都会看到。</p> <ul><li>不可能你什么都不做就跟框架搭配在一起，这个是不可能的。</li></ul> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722115249951.png" alt="image-20210722115249951"></p> <ul><li><p>好其实已经等于讲过了源代码了，不过大家不太熟悉这种形式的话，我们还是把源代码看一遍。</p></li> <li><p>为什么要写第2个构造函数？所以我们这这才因此啊我们导出了第二个构造函数。</p></li> <li><p>那第二个构造函数它应该是放在私有端私有区域还是保护区域，还是公开区域呢？不可以放在公开区域，因为现在这些东西就是不准备外不打算被外界去创建，是要通过原型来创建，所以这个不可以是正号，public，那它是private负号或者是protect的井号都可以都可以，只要能够跟上面这个区隔开来。</p></li></ul> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210722115337016.png" alt="image-20210722115337016"></p> <ul><li>所以我们从前面看的好几个我给的例子，我每次谈到设计模式就好像怕。
又怕呢。是吓着了比较初学的、经验比较少的人。
但其实设计模式就是我们在学习面向对象设计的过程之中一个必经的路程。
<ul><li>已经有些人整理出一些很常见的问题，然后他们也整理出很好的方法。用多少个类，彼此用那3把武器怎么样组合它们？</li> <li>就能够解决了这些问题，已经有人把它整理好了。</li></ul></li> <li>然后我们也学习到了所谓设计模式里面的经典的做法，我们从中来学习类跟类之间如何关联起来。</li> <li>那其实面向对象的设计是一条比较长远的路，因为它不像传统的那一种编程语言啊，谁调用谁，谁调用谁，这个线索非常的清楚。</li> <li>这个面向对象呢，不是这个样子。所以这里面有很多抽象的思考啊，需要大家在这个学习过程里面呢不断地去想啊，为什么这样？
该怎么该怎么构思？如何去写你的class啊？
不断地去写代码，在这个过程里面你才能够有真正的进步。</li> <li>课程结束</li></ul> <h2 id="参考资料"><a href="#参考资料" class="header-anchor">#</a> 参考资料</h2> <ul><li>C++<a href="https://mooc.study.163.com/smartSpec/detail/1001137001.htm" target="_blank" rel="noopener noreferrer">网易云微专业<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a>，侯捷</li></ul></div> <div class="page-edit"><!----> <!----></div> <!----> </div> <!----></div></div>
    <script src="/assets/js/app.c70e21ad.js" defer></script><script src="/assets/js/28.9523cb32.js" defer></script>
  </body>
</html>
